use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class BlockRecoverPointIngestOrchestrator method performRPExportIngestion.
/**
* RecoverPoint volumes are expected to have export masks where the volume is exported to
* a RecoverPoint site. Therefore every RP volume (sources, targets, journals) will need to
* go through this code and have their export mask ingested. Even if the mask has already been
* ingested by a previous volume ingestion, this method still needs to update the ExportGroup and
* ExportMask objects to reflect the newly ingested volume as part of its management.
*
* @param volumeContext the RecoverPointVolumeIngestionContext for the volume currently being ingested
* @param unManagedVolume unmanaged volume
* @param volume managed volume
* @return managed volume with export ingested
*/
private void performRPExportIngestion(IngestionRequestContext parentRequestContext, RecoverPointVolumeIngestionContext volumeContext, UnManagedVolume unManagedVolume, Volume volume) {
_logger.info("starting RecoverPoint export ingestion for volume {}", volume.forDisplay());
Project project = volumeContext.getProject();
ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, volume.getStorageController());
List<UnManagedExportMask> unManagedRPExportMasks = findUnManagedRPExportMask(protectionSystem, unManagedVolume);
if (unManagedRPExportMasks.isEmpty()) {
_logger.error("Could not find any unmanaged export masks associated with volume: " + unManagedVolume.getLabel());
throw IngestionException.exceptions.noUnManagedExportMaskFound(unManagedVolume.getNativeGuid());
}
// Keep a map for internal site name name and varray
Map<String, VirtualArray> internalSiteToVarrayMap = new HashMap<String, VirtualArray>();
internalSiteToVarrayMap.put(volume.getInternalSiteName(), volumeContext.getVarray(unManagedVolume));
// If this is a MetroPoint volume we're going to have multiple ExportMasks/ExportGroups to deal with.
// We'll need to query the backend volumes for extra info to populate internalSiteToVarrayMap so
// we can properly line up the ExportMasks/ExportGroups.
boolean metropoint = RPHelper.isMetroPointVolume(_dbClient, volume);
if (metropoint) {
// We need the VPLEX ingest context to get the backend volume info
VplexVolumeIngestionContext vplexVolumeContext = ((RpVplexVolumeIngestionContext) volumeContext.getVolumeContext()).getVplexVolumeIngestionContext();
for (String associatedVolumeIdStr : vplexVolumeContext.getAssociatedVolumeIds(volume)) {
// Find the associated volumes using the context maps or the db if they are already there
Volume associatedVolume = VolumeIngestionUtil.findVolume(_dbClient, vplexVolumeContext.getBlockObjectsToBeCreatedMap(), vplexVolumeContext.getDataObjectsToBeUpdatedMap(), associatedVolumeIdStr);
String internalSiteName = associatedVolume.getInternalSiteName();
// If we don't already have an entry for this internal site name, let's add it now.
if (!internalSiteToVarrayMap.containsKey(internalSiteName)) {
internalSiteToVarrayMap.put(internalSiteName, _dbClient.queryObject(VirtualArray.class, associatedVolume.getVirtualArray()));
}
}
}
// this will more than likely only loop once.
for (Entry<String, VirtualArray> entry : internalSiteToVarrayMap.entrySet()) {
String internalSiteName = entry.getKey();
VirtualArray virtualArray = entry.getValue();
UnManagedExportMask em = null;
if (metropoint) {
// Since we're flagged for MetroPoint we need to determine which ExportMask to use.
// We need the MetroPoint volume to be added to BOTH ExportGroups that represent the
// two Storage Views on VPLEX for cluster-1 and cluster-2.
// So let's use the varray to find the cluster we're looking for on this pass and match
// it to the maskingViewParth of the UnManagedExportMask.
// This should line things up roughly as:
// VPLEX Storage View 1 -> VPLEX Cluster1 + RPA1
// VPLEX Storage View 2 -> VPLEX Cluster2 + RPA2
String vplexCluster = ConnectivityUtil.getVplexClusterForVarray(virtualArray.getId(), storageSystem.getId(), _dbClient);
// First try and match based on UnManagedExportMask ports
for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
for (String portUri : exportMask.getKnownStoragePortUris()) {
StoragePort port = _dbClient.queryObject(StoragePort.class, URI.create(portUri));
if (port != null && !port.getInactive()) {
String vplexClusterForMask = ConnectivityUtil.getVplexClusterOfPort(port);
if (vplexCluster.equals(vplexClusterForMask)) {
em = exportMask;
break;
}
}
}
if (em != null) {
break;
}
}
if (em == null) {
// It really shouldn't come to this, but leaving this code just in case.
for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
if (exportMask.getMaskingViewPath().contains("cluster-" + vplexCluster)) {
em = exportMask;
break;
}
}
}
} else {
em = unManagedRPExportMasks.get(0);
}
// If the mask for ingested volume is in a mask that contains JOURNAL keyword, make sure the ExportGroup created contains
// that internal flag.
boolean isJournalExport = false;
if (em.getMaskName().toLowerCase().contains(VolumeIngestionUtil.RP_JOURNAL)) {
isJournalExport = true;
}
String exportGroupGeneratedName = RPHelper.generateExportGroupName(protectionSystem, storageSystem, internalSiteName, virtualArray, isJournalExport);
ExportGroup exportGroup = VolumeIngestionUtil.verifyExportGroupExists(parentRequestContext, exportGroupGeneratedName, project.getId(), em.getKnownInitiatorUris(), virtualArray.getId(), _dbClient);
boolean exportGroupCreated = false;
if (null == exportGroup) {
exportGroupCreated = true;
Integer numPaths = em.getZoningMap().size();
_logger.info("Creating Export Group with label {}", em.getMaskName());
exportGroup = RPHelper.createRPExportGroup(exportGroupGeneratedName, virtualArray, project, numPaths, isJournalExport);
}
if (null != exportGroup) {
// check if the ExportGroup has already been fetched
ExportGroup loadedExportGroup = parentRequestContext.findExportGroup(exportGroup.getLabel(), project.getId(), virtualArray.getId(), null, null);
if (null != loadedExportGroup) {
exportGroup = loadedExportGroup;
}
}
volumeContext.setExportGroup(exportGroup);
volumeContext.setExportGroupCreated(exportGroupCreated);
volumeContext.getRpExportGroupMap().put(exportGroup, exportGroupCreated);
// set RP device initiators to be used as the "host" for export mask ingestion
List<Initiator> initiators = new ArrayList<Initiator>();
Iterator<Initiator> initiatorItr = _dbClient.queryIterativeObjects(Initiator.class, URIUtil.toURIList(em.getKnownInitiatorUris()));
while (initiatorItr.hasNext()) {
initiators.add(initiatorItr.next());
}
volumeContext.setDeviceInitiators(initiators);
// find the ingest export strategy and call into for this unmanaged export mask
IngestExportStrategy ingestStrategy = ingestStrategyFactory.buildIngestExportStrategy(unManagedVolume);
volume = ingestStrategy.ingestExportMasks(unManagedVolume, volume, volumeContext);
if (null == volume) {
// ingestion did not succeed, but in case it wasn't, throw one
throw IngestionException.exceptions.generalVolumeException(unManagedVolume.getLabel(), "check the logs for more details");
}
}
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class BlockVplexVolumeIngestOrchestrator method findOrCreateExportGroup.
/**
* Find or Create an ExportGroup.
*
* @param vplex -- VPLEX StorageSystem
* @param array -- Array StorageSystem
* @param initiators -- Collection<Initiator> representing VPLEX back-end ports.
* @param virtualArrayURI
* @param projectURI
* @param tenantURI
* @param numPaths Value of maxPaths to be put in ExportGroup
* @param unmanagedExportMask the unmanaged export mask
* @return existing or newly created ExportGroup (not yet persisted)
*/
private ExportGroup findOrCreateExportGroup(IngestionRequestContext requestContext, StorageSystem array, Collection<Initiator> initiators, URI virtualArrayURI, URI projectURI, URI tenantURI, int numPaths, UnManagedExportMask unmanagedExportMask) {
StorageSystem vplex = requestContext.getStorageSystem();
String arrayName = array.getSystemType().replace("block", "") + array.getSerialNumber().substring(array.getSerialNumber().length() - 4);
String groupName = unmanagedExportMask.getMaskName() + "_" + arrayName;
ExportGroup exportGroup = requestContext.findExportGroup(groupName, projectURI, virtualArrayURI, null, null);
if (null != exportGroup) {
_logger.info(String.format("Returning existing ExportGroup %s", exportGroup.getLabel()));
return exportGroup;
}
List<ExportGroup> exportGroups = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, ExportGroup.class, PrefixConstraint.Factory.getFullMatchConstraint(ExportGroup.class, "label", groupName));
if (null != exportGroups && !exportGroups.isEmpty()) {
for (ExportGroup group : exportGroups) {
if (null != group) {
_logger.info(String.format("Returning existing ExportGroup %s", group.getLabel()));
exportGroup = group;
}
}
} else {
Map<String, ExportGroup> possibleExportGroups = new HashMap<String, ExportGroup>();
Set<String> initiatorUris = new HashSet<String>();
for (Initiator initiator : initiators) {
// Determine all the possible existing Export Groups
List<ExportGroup> groups = ExportUtils.getInitiatorExportGroups(initiator, _dbClient);
for (ExportGroup group : groups) {
if (!possibleExportGroups.containsKey(group.getId().toString())) {
possibleExportGroups.put(group.getId().toString(), group);
}
}
initiatorUris.add(initiator.getId().toString());
}
// If there are possible Export Groups, look for one with that matches on inits, varray, project, and tenant.
for (ExportGroup group : possibleExportGroups.values()) {
if (URIUtil.identical(group.getVirtualArray(), virtualArrayURI) && URIUtil.identical(group.getProject().getURI(), projectURI) && URIUtil.identical(group.getTenant().getURI(), tenantURI)) {
if (group.getInitiators().containsAll(initiatorUris)) {
_logger.info(String.format("Returning existing ExportGroup %s from database.", group.getLabel()));
return group;
}
}
}
// No existing group has the mask, let's create one.
exportGroup = new ExportGroup();
exportGroup.setLabel(groupName);
exportGroup.setProject(new NamedURI(projectURI, exportGroup.getLabel()));
exportGroup.setVirtualArray(vplex.getVirtualArray());
exportGroup.setTenant(new NamedURI(tenantURI, exportGroup.getLabel()));
exportGroup.setGeneratedName(groupName);
exportGroup.setVolumes(new StringMap());
exportGroup.setOpStatus(new OpStatusMap());
exportGroup.setVirtualArray(virtualArrayURI);
exportGroup.setNumPaths(numPaths);
// Add the initiators into the ExportGroup.
for (Initiator initiator : initiators) {
exportGroup.addInitiator(initiator);
}
_logger.info(String.format("Returning new ExportGroup %s", exportGroup.getLabel()));
}
return exportGroup;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class ExportService method searchInDb.
// Sometimes there are multiple entries for the same initiator
// and so we return a list here
private Boolean searchInDb(String port, List<Initiator> list, String protocol) {
SearchedResRepList resRepList = new SearchedResRepList(ResourceTypeEnum.INITIATOR);
Boolean found = false;
String formattedStr = "";
if (protocol.equalsIgnoreCase(Protocol.FC.name())) {
int index = 0;
while (index < (port.length())) {
formattedStr += port.substring(index, index + 2).toUpperCase();
index = index + 2;
if (index < (port.length())) {
formattedStr += ":";
}
}
} else if (protocol.equalsIgnoreCase(Protocol.iSCSI.name())) {
formattedStr = port;
}
// Finds the Initiator that includes the initiator port specified, if any.
_dbClient.queryByConstraint(AlternateIdConstraint.Factory.getInitiatorPortInitiatorConstraint(formattedStr), resRepList);
if (resRepList.iterator() != null) {
for (SearchResultResourceRep res : resRepList) {
Initiator initiator = _dbClient.queryObject(Initiator.class, res.getId());
if ((initiator != null) && !(initiator.getInactive())) {
list.add(initiator);
_log.info("Found initiator in DB for port = {}", port);
found = true;
}
}
}
return found;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class ExportService method getListOfInitiators.
private List<Initiator> getListOfInitiators(Connector connector, String tenant_id, String protocol, Volume vol) {
List<Initiator> initiators = new ArrayList<Initiator>();
boolean bFound = false;
if (protocol.equals(Protocol.iSCSI.name())) {
// this is an iSCSI request
String port = connector.initiator;
String hostname = connector.host;
List<Initiator> iscsi_initiators = new ArrayList<Initiator>();
Boolean found = searchInDb(port, iscsi_initiators, Protocol.iSCSI.name());
if (found) {
initiators.addAll(iscsi_initiators);
} else {
// not found, create a new one
_log.info("Creating new iSCSI initiator, iqn = {}", port);
// Make sure the port is a valid iSCSI port.
if (!iSCSIUtility.isValidIQNPortName(port) && !iSCSIUtility.isValidEUIPortName(port))
throw APIException.badRequests.invalidIscsiInitiatorPort();
// Find host, and if not found, create new host
Host host = getHost(hostname, tenant_id);
// create and populate the initiator
Initiator initiator = new Initiator();
initiator.setHost(host.getId());
initiator.setHostName(connector.host);
if (!NullColumnValueGetter.isNullURI(host.getCluster())) {
Cluster cluster = queryObject(Cluster.class, host.getCluster(), false);
initiator.setClusterName(cluster.getLabel());
}
initiator.setId(URIUtil.createId(Initiator.class));
initiator.setInitiatorPort(port);
// allows deletion via UI
initiator.setIsManualCreation(true);
initiator.setProtocol(HostInterface.Protocol.iSCSI.name());
addInitiatorToNetwork(initiator, vol);
ScopedLabelSet tags = new ScopedLabelSet();
tags.add(new ScopedLabel("openstack", "dynamic"));
initiator.setTag(tags);
_dbClient.createObject(initiator);
initiators.add(initiator);
}
} else if (protocol.equals(Protocol.FC.name())) {
// this is an FC request
for (String fc_port : connector.wwpns) {
// See if this initiator exists in our DB
List<Initiator> fc_initiators = new ArrayList<Initiator>();
Boolean found = searchInDb(fc_port, fc_initiators, Protocol.FC.name());
if (found) {
bFound = true;
initiators.addAll(fc_initiators);
} else {
// not found, we don't create dynamically for FC
_log.info("FC initiator for wwpn {} not found", fc_port);
}
}
if (!bFound) {
throw APIException.internalServerErrors.genericApisvcError("Export Failed", new Exception("No FC initiator found for export"));
}
} else {
throw APIException.internalServerErrors.genericApisvcError("Unsupported volume protocol", new Exception("The protocol specified is not supported. The protocols supported are " + Protocol.FC.name() + " and " + Protocol.iSCSI.name()));
}
return initiators;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class ExportService method processDetachRequest.
// INTERNAL FUNCTIONS
private boolean processDetachRequest(Volume vol, VolumeActionRequest.DetachVolume detach, String openstackTenantId, String protocol) throws InterruptedException {
_log.info("Detach request");
// Step 1: Find export group of volume
ExportGroup exportGroup = findExportGroup(vol);
if (exportGroup == null)
throw APIException.badRequests.parameterIsNotValid("volume_id");
Set<URI> addedClusters = new HashSet<>();
Set<URI> removedClusters = new HashSet<>();
Set<URI> addedHosts = new HashSet<>();
Set<URI> removedHosts = new HashSet<>();
Set<URI> addedInitiators = new HashSet<>();
Set<URI> removedInitiators = new HashSet<>();
// Step 2: Validate initiators are part of export group
List<URI> currentURIs = new ArrayList<URI>();
List<Initiator> detachInitiators = getListOfInitiators(detach.connector, openstackTenantId, protocol, vol);
currentURIs = StringSetUtil.stringSetToUriList(exportGroup.getInitiators());
for (Initiator initiator : detachInitiators) {
URI uri = initiator.getId();
if (!currentURIs.contains(uri)) {
throw APIException.badRequests.parameterIsNotValid("volume_id");
}
removedInitiators.add(uri);
}
_log.info("updateExportGroup request is submitted.");
// get block controller
BlockExportController exportController = getController(BlockExportController.class, BlockExportController.EXPORT);
// Now update export group
String task = UUID.randomUUID().toString();
initTaskStatus(exportGroup, task, Operation.Status.pending, ResourceOperationTypeEnum.DELETE_EXPORT_VOLUME);
Map<URI, Integer> noUpdatesVolumeMap = new HashMap<URI, Integer>();
exportController.exportGroupUpdate(exportGroup.getId(), noUpdatesVolumeMap, noUpdatesVolumeMap, addedClusters, removedClusters, addedHosts, removedHosts, addedInitiators, removedInitiators, task);
return waitForTaskCompletion(exportGroup.getId(), task);
// TODO: If now the list is empty, change volume status to 'not exported'
// and delete the exportGroup
}
Aggregations