in automation/tinc/main/ext/qautils/gppylib/programs/clsRecoverSegment.py [0:0]
def getRecoveryActionsFromConfiguration(self, gpEnv, gpArray):
"""
getRecoveryActionsFromConfiguration
returns a GpMirrorListToBuild object
"""
segments = gpArray.getSegDbList()
failedSegments = [ seg for seg in segments if seg.isSegmentDown() ]
peersForFailedSegments = self.findAndValidatePeersForFailedSegments(gpArray, failedSegments)
# Dictionaries used for building mapping to new hosts
recoverAddressMap = {}
recoverHostMap = {}
interfaceHostnameWarnings = []
# Check if the array is a "standard" array
(isStandardArray, _ignore) = gpArray.isStandardArray()
recoverHostIdx = 0
if self.__options.newRecoverHosts and len(self.__options.newRecoverHosts) > 0:
for seg in failedSegments:
segAddress = seg.getSegmentAddress()
segHostname = seg.getSegmentHostName()
# Haven't seen this hostname before so we put it on a new host
if not recoverHostMap.has_key(segHostname):
try:
recoverHostMap[segHostname] = self.__options.newRecoverHosts[recoverHostIdx]
except:
# If we get here, not enough hosts were specified in the -p option. Need 1 new host
# per 1 failed host.
raise Exception('Not enough new recovery hosts given for recovery.')
recoverHostIdx += 1
if isStandardArray:
# We have a standard array configuration, so we'll try to use the same
# interface naming convention. If this doesn't work, we'll correct it
# below on name lookup
segInterface = segAddress[segAddress.rfind('-'):]
destAddress = recoverHostMap[segHostname] + segInterface
destHostname = recoverHostMap[segHostname]
else:
# Non standard configuration so we won't make assumptions on
# naming. Instead we'll use the hostname passed in for both
# hostname and address and flag for warning later.
destAddress = recoverHostMap[segHostname]
destHostname = recoverHostMap[segHostname]
# Save off the new host/address for this address.
recoverAddressMap[segAddress] = (destHostname, destAddress)
# Now that we've generated the mapping, look up all the addresses to make
# sure they are resolvable.
interfaces = [address for (_ignore, address) in recoverAddressMap.values()]
interfaceLookup = GpInterfaceToHostNameCache(self.__pool, interfaces, [None] * len(interfaces))
for key in recoverAddressMap.keys():
(newHostname, newAddress) = recoverAddressMap[key]
try:
addressHostnameLookup = interfaceLookup.getHostName(newAddress)
# Lookup failed so use hostname passed in for everything.
if addressHostnameLookup is None:
interfaceHostnameWarnings.append("Lookup of %s failed. Using %s for both hostname and address." % (newAddress, newHostname))
newAddress = newHostname
except:
# Catch all exceptions. We will use hostname instead of address
# that we generated.
interfaceHostnameWarnings.append("Lookup of %s failed. Using %s for both hostname and address." % (newAddress, newHostname))
newAddress = newHostname
# if we've updated the address to use the hostname because of lookup failure
# make sure the hostname is resolvable and up
if newHostname == newAddress:
try:
unix.Ping.local("ping new hostname", newHostname)
except:
raise Exception("Ping of host %s failed." % newHostname)
# Save changes in map
recoverAddressMap[key] = (newHostname, newAddress)
if len(self.__options.newRecoverHosts) != recoverHostIdx:
interfaceHostnameWarnings.append("The following recovery hosts were not needed:")
for h in self.__options.newRecoverHosts[recoverHostIdx:]:
interfaceHostnameWarnings.append("\t%s" % h)
spareDirectoryMap = None
if self.__options.spareDataDirectoryFile is not None:
spareDirectoryMap = self.__readSpareDirectoryMap(gpArray, self.__options.spareDataDirectoryFile)
portAssigner = PortAssigner(gpArray)
forceFull = self.__options.forceFullResynchronization
segs = []
for i in range(len(failedSegments)):
failoverSegment = None
failedSegment = failedSegments[i]
liveSegment = peersForFailedSegments[i]
if self.__options.newRecoverHosts and len(self.__options.newRecoverHosts) > 0:
(newRecoverHost, newRecoverAddress) = recoverAddressMap[failedSegment.getSegmentAddress()]
# these two lines make it so that failoverSegment points to the object that is registered in gparray
failoverSegment = failedSegment
failedSegment = failoverSegment.copy()
failoverSegment.setSegmentHostName( newRecoverHost )
failoverSegment.setSegmentAddress( newRecoverAddress )
port = portAssigner.findAndReservePort(False, newRecoverHost, newRecoverAddress )
replicationPort = portAssigner.findAndReservePort(True, newRecoverHost, newRecoverAddress )
failoverSegment.setSegmentPort( port )
failoverSegment.setSegmentReplicationPort( replicationPort)
if spareDirectoryMap is not None:
#
# these two lines make it so that failoverSegment points to the object that is registered in gparray
failoverSegment = failedSegment
failedSegment = failoverSegment.copy()
self.__applySpareDirectoryMapToSegment( gpEnv, gpArray, spareDirectoryMap, failoverSegment)
# we're failing over to different location on same host so we don't need to assign new ports
segs.append( GpMirrorToBuild(failedSegment, liveSegment, failoverSegment, forceFull ))
return GpMirrorListToBuild(segs, self.__pool, self.__options.quiet, self.__options.parallelDegree, interfaceHostnameWarnings)