def buildMirrors()

in automation/tinc/main/ext/qautils/gppylib/operations/buildMirrorSegments.py [0:0]


    def buildMirrors(self, actionName, gpEnv, gpArray):
        """
        Build the mirrors.

        gpArray must have already been altered to have updated directories -- that is, the failoverSegments
            from the mirrorsToBuild must be present in gpArray.

        """
        testOutput("building %s segment(s)" % len(self.__mirrorsToBuild))

        if len(self.__mirrorsToBuild) == 0:
            logger.info("No segments to " + actionName)
            return

        self.checkForPortAndDirectoryConflicts(gpArray)

        logger.info("%s segment(s) to %s" % (len(self.__mirrorsToBuild), actionName))

        self.__verifyGpArrayContents(gpArray)

        # make sure the target directories are up-to-date
        #  by cleaning them, if needed, and then copying a basic directory there
        #  the postgresql.conf in that basic directory will need updating (to change the port)
        toStopDirectives = []
        toEnsureMarkedDown = []
        cleanupDirectives = []
        copyDirectives = []
        for toRecover in self.__mirrorsToBuild:

            if toRecover.getFailedSegment() is not None:
                # will stop the failed segment.  Note that we do this even if we are recovering to a different location!
                toStopDirectives.append(GpStopSegmentDirectoryDirective(toRecover.getFailedSegment()))
                if toRecover.getFailedSegment().getSegmentStatus() == gparray.STATUS_UP:
                    toEnsureMarkedDown.append(toRecover.getFailedSegment())

            if toRecover.isFullSynchronization():

                isTargetReusedLocation = False
                if toRecover.getFailedSegment() is not None and \
                    toRecover.getFailoverSegment() is None:
                    #
                    # We are recovering a failed segment in-place
                    #
                    cleanupDirectives.append(GpCleanupSegmentDirectoryDirective(toRecover.getFailedSegment()))
                    isTargetReusedLocation = True

                if toRecover.getFailoverSegment() is not None:
                    targetSegment = toRecover.getFailoverSegment()
                else: targetSegment = toRecover.getFailedSegment()

                d = GpCopySegmentDirectoryDirective(toRecover.getLiveSegment(), targetSegment, isTargetReusedLocation)
                copyDirectives.append(d)

        self.__ensureStopped(gpEnv, toStopDirectives)
        self.__ensureMarkedDown(gpEnv, toEnsureMarkedDown)
        self.__cleanUpSegmentDirectories(cleanupDirectives)
        self.__copySegmentDirectories(gpEnv, gpArray, copyDirectives)

        # update and save metadata in memory
        for toRecover in self.__mirrorsToBuild:

            if toRecover.getFailoverSegment() is None:
                # we are recovering the lost segment in place
                seg = toRecover.getFailedSegment()
            else:
                seg = toRecover.getFailedSegment()
                # no need to update the failed segment's information -- it is
                #   being overwritten in the configuration with the failover segment
                for gpArraySegment in gpArray.getDbList():
                    if gpArraySegment is seg:
                        raise Exception("failed segment should not be in the new configuration if failing over to new segment")

                seg = toRecover.getFailoverSegment()
            seg.setSegmentStatus(gparray.STATUS_DOWN) # down initially, we haven't started it yet
            seg.setSegmentMode(gparray.MODE_RESYNCHRONIZATION)

        # figure out what needs to be started or transitioned
        mirrorsToStart = []
        primariesToConvert = []
        convertPrimaryUsingFullResync = []
        fullResyncMirrorDbIds = {}
        for toRecover in self.__mirrorsToBuild:
            seg = toRecover.getFailoverSegment()
            if seg is None:
                seg = toRecover.getFailedSegment() # we are recovering in place
            mirrorsToStart.append(seg)
            primarySeg = toRecover.getLiveSegment()
            # The change in configuration to of the mirror to down requires
            # that the primary also be change to change tracking if required.
            if primarySeg.getSegmentMode() != gparray.MODE_CHANGELOGGING:
                primarySeg.setSegmentMode(gparray.MODE_CHANGELOGGING)
            primariesToConvert.append(primarySeg)
            convertPrimaryUsingFullResync.append(toRecover.isFullSynchronization())

            if toRecover.isFullSynchronization() and seg.getSegmentDbId() > 0:
                fullResyncMirrorDbIds[seg.getSegmentDbId()] = True

        # should use mainUtils.getProgramName but I can't make it work!
        programName = os.path.split(sys.argv[0])[-1]

        # Disable Ctrl-C, going to save metadata in database and transition segments
        signal.signal(signal.SIGINT,signal.SIG_IGN)
        try:
            logger.info("Updating configuration with new mirrors")
            configInterface.getConfigurationProvider().updateSystemConfig(
                gpArray,
                "%s: segment config for resync" % programName,
                dbIdToForceMirrorRemoveAdd = fullResyncMirrorDbIds, 
                useUtilityMode = False, 
                allowPrimary = False 
            )
            
            MPP_12038_fault_injection()
            
            logger.info("Updating mirrors")
            self.__updateGpIdFile(gpEnv, gpArray, mirrorsToStart)

            logger.info("Starting mirrors")
            self.__startAll(gpEnv, gpArray, mirrorsToStart)
            
            logger.info("Updating configuration to mark mirrors up")
            for seg in mirrorsToStart:
                seg.setSegmentStatus(gparray.STATUS_UP)
            for seg in primariesToConvert:
                seg.setSegmentMode(gparray.MODE_RESYNCHRONIZATION)
            configInterface.getConfigurationProvider().updateSystemConfig(
                gpArray,
                "%s: segment resync marking mirrors up and primaries resync" % programName,
                dbIdToForceMirrorRemoveAdd = {},
                useUtilityMode = True,
                allowPrimary = False
            )

            MPP_12038_fault_injection()

            #
            # note: converting the primaries may take a really long time to complete because of initializing
            #       resynchronization
            #
            logger.info("Updating primaries")
            self.__convertAllPrimaries(gpEnv, gpArray, primariesToConvert, convertPrimaryUsingFullResync)

            logger.info("Done updating primaries")
        finally:
            # Reenable Ctrl-C
            signal.signal(signal.SIGINT,signal.default_int_handler)