Ejemplo n.º 1
0
def main(jsonDoc):
    # Logger setup
    try:
        logging.basicConfig(filename='/var/log/boru.log',
                            level=logging.INFO,
                            format="%(asctime)s: %(levelname)s: %(message)s")
        log = logging.getLogger('awsResume')
    except Exception as e:
        # Logging* just print, can't log
        print("[awsResume] Critical Logger Setup Error: {}".format(str(e)))
        # Exit
        return

    # Extracting the taskId and accountName for the DBConnect to start working from the next step
    try:
        taskId = jsonDoc['task_id']
        accountName = jsonDoc["lab"]
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsResume] Critical Error extracting 'taskId' and 'accountName' from 'jsonDoc': {}".format(
            str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # Extract parameters from main(jsonDoc)
    try:
        region = jsonDoc["region"]
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsResume] Critical Error Extracting 'jsonDoc' Parameters: {}".format(
            str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # variables
    listOfInstancesIdsRaw = []
    listOfInstancesIdsFiltered = []
    listOfInstancesStates = []

    # ==========================
    # Creating the boto3 session
    # ==========================
    try:
        # Session [Most Important] | Used to access student child accounts
        session = boto3.Session(profile_name=accountName, region_name=region)
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsResume | {}] Failed to create a boto3 session. Error: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # =============================
    # Getting all EC2 Instances Ids
    # =============================
    try:
        getAllEc2Instances(session, listOfInstancesIdsRaw,
                           listOfInstancesStates, accountName, log)
    except Exception as e:
        errorExceptionInfo = "[awsResume | {}] Failed to Get EC2 Instances. Error: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # ================================================
    # Filter any terminated instances to prevent error
    # ================================================
    try:
        if (listOfInstancesIdsRaw):
            filterInstances(listOfInstancesIdsRaw, listOfInstancesStates,
                            listOfInstancesIdsFiltered, accountName, log)
    except Exception as e:
        errorExceptionInfo = "[awsResume | {}] Failed to Filter EC2 Instances. Error: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # ==============================
    # Starting all EC2 Instances Ids
    # ==============================
    if (listOfInstancesIdsFiltered):
        try:
            startAllEc2Instances(session, listOfInstancesIdsFiltered,
                                 accountName, log)
            # give time for the request to go through and start stopping instances
            time.sleep(10)
            # timeout variable
            timeoutCounter = 0

            # check if the instances have running
            while True:
                # variables to determine instance status
                instancesStates = []
                completeInstanceStatusCounter = 0
                # getting the state/status of each filtered instance
                for instanceId in listOfInstancesIdsFiltered:
                    getInstanceStatus(instanceId, instancesStates, session)
                # if instance is running, add +1 to counter for every instance running
                for instanceStatus in instancesStates:
                    # stack success
                    if (instanceStatus == 'running'):
                        completeInstanceStatusCounter += 1

                # success, the number of running instances in the counter matches the length of a list of instances
                if (completeInstanceStatusCounter == len(instancesStates)):
                    # update task status to ready
                    # DBConnect ============================
                    # Update task['taskStatus']
                    DBConnect.setTaskStatusToReady(taskId)
                    # ======================================
                    # logging
                    log.info(
                        "[awsResume | {}] Resume successful. Marked task as ready."
                        .format(str(accountName)))
                    return

                # exit with timeout of 60 min
                elif (timeoutCounter > 60):
                    # update task status error error
                    errorExceptionInfo = "[awsResume | {}] Timeout error. Marked task as error.".format(
                        str(accountName))
                    log.error(errorExceptionInfo)
                    # DBConnect ============================
                    # Update task['errorInfo']
                    DBConnect.appendTaskErrorInfo(taskId, accountName,
                                                  errorExceptionInfo)
                    # Update task['taskStatus']
                    DBConnect.setTaskStatusToError(taskId)
                    # ======================================
                    return
                # add to counter
                timeoutCounter += 1
                # sleep timer
                time.sleep(60)
        except Exception as e:
            # logging
            errorExceptionInfo = "[awsResume | {}] Failed to Stop EC2 Instances. Error: {}".format(
                str(accountName), str(e))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            return
    else:
        log.warning("[awsResume | {}] No Instances found to stop.".format(
            str(accountName)))
        # DBConnect ============================
        # Update task['taskStatus']
        DBConnect.setTaskStatusToReady(taskId)
        # ======================================
        return
Ejemplo n.º 2
0
def main(jsonDoc):
    # Example of 'jsonDoc'
    '''
  {
    "task_id" : "abc111555566abbca",
    "lab" : "Student01",
    "courseName" : "ANYDC",
    Everything passed in from the 'generateStartLabTaskBuffer' function in the scheduler,
    along with cloudFormation parameters processed by the scheduler.
  }
  '''

    # Logger setup
    try:
        logging.basicConfig(filename='/var/log/boru.log',
                            level=logging.INFO,
                            format="%(asctime)s: %(levelname)s: %(message)s")
        log = logging.getLogger('awsStart')
    except Exception as e:
        # Logging* just print, can't log
        print("[awsStart] Critical Logger Setup Error: {}".format(str(e)))
        # Exit
        return

    # Extracting the taskId and accountName for the DBConnect to start working from the next step
    try:
        taskId = jsonDoc['task_id']
        accountName = jsonDoc['lab']
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart] Critical Error extracting 'taskId' and 'accountName' from 'jsonDoc': {}".format(
            str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # Extract parameters from main(jsonDoc)
    try:
        courseName = jsonDoc['courseName']
        startDate = jsonDoc['startDate']
        finishDate = jsonDoc['finishDate']
        timezone = jsonDoc['timezone']
        instructor = jsonDoc['instructor']
        tag = jsonDoc['tag']
        region = jsonDoc['region']
        cloudFormationParameters = jsonDoc['parameters']
        startTemplateUrl = jsonDoc['courseTemplate']
        sensorTemplate = jsonDoc['sensorTemplate']
        sensor = jsonDoc['sensor']
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart] Critical Error Extracting 'jsonDoc' Parameters: {}".format(
            str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return
    ''' Below the main stuff happens '''
    # Just a sleep timer variable. Call him Gary
    garyTheSnail = 30

    # ===================
    # Generate Stack Name
    # ===================
    # The stackName will look similar to: 'ANYDC-2-4Jul-Central-joriordan-ANYDC-CET-LabsTest'
    # This name will be passed into 'cloudFormation.create_stack' as the 'StackName'
    ''' !!! If ANYDC removed from tag, add courseName to start, Else, dont add courseName'''
    try:
        stackName = generateStackName(courseName, startDate, finishDate,
                                      timezone, instructor, tag)
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error generating the stack name: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # ====================================================
    # Create a boto3 session and a cloudFormation resource
    # ====================================================
    # Creating the boto3 session that will communicate with AWS.
    # Creating a session resource for a cloudFormation
    try:
        session = boto3.Session(profile_name=accountName, region_name=region)
        cloudFormation = session.resource('cloudformation')
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error creating the boto3 session: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # ==================================================================
    # Extracting all cloudFormationParameters from jsonDoc['parameters']
    # ==================================================================
    # Extracting all the raw parameters into lists that will be used to create a
    # 'cloudFormationParametersBuffer', which will be passed into 'cloudFormation.create_stack'
    try:
        # Buffer, will be ignored
        parametersKeysBuffer = []
        parametersValsBuffer = []
        # Add to the buffer
        for param in cloudFormationParameters[0]:
            parametersKeysBuffer.append(list(param.keys()))
            parametersValsBuffer.append(list(param.values()))

        # Final keys and values
        cloudFormationParametersKeys = []
        cloudFormationParametersVals = []

        # Extracting keys
        for item in parametersKeysBuffer:
            cloudFormationParametersKeys.append(item[0])
        # Extracting values
        for item in parametersValsBuffer:
            cloudFormationParametersVals.append(item[0])
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error extracting cloudFormation parameters: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # ================================
    # cloudFormation Parameters Buffer
    # ================================
    # This buffer is passed into 'cloudFormation.create_stack'
    try:
        # The buffer containing all cloudFormationParametersKeys and parametersValsBuffer ready for 'cloudFormation.create_stack'
        parametersBuffer = []
        # Creating the buffer
        for paramIndex in range(len(cloudFormationParametersKeys)):
            parametersBuffer.append({
                'ParameterKey':
                str(cloudFormationParametersKeys[paramIndex]),
                'ParameterValue':
                str(cloudFormationParametersVals[paramIndex])
            })
        # logging
        log.info("[awsStart | {}] Course Parameters Buffer: {}".format(
            str(accountName), str(parametersBuffer)))
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error creating cloudFormation parameters buffer: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # =====================
    # Cloud Formation Stack
    # =====================
    # Creating the cloudFormation stack in AWS using 'cloudFormation.create_stack'
    try:
        cloudFormation.create_stack(StackName=str(stackName),
                                    TemplateURL=str(startTemplateUrl),
                                    Parameters=parametersBuffer,
                                    Capabilities=['CAPABILITY_NAMED_IAM'])
        # logging
        log.info("[awsStart | {}] starting course cloudFormation...".format(
            str(accountName)))
        # Wait Gary number seconds to give time for AWS to set up stacks. Stack creation will take many minutes anyway
        time.sleep(garyTheSnail)
    except Exception as e:
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error creating AWS stack: {}".format(
            str(accountName), str(e))
        log.exception(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return

    # =====================
    # |Query the AWS Stack|
    # =====================
    # Query the AWS Stack and wait until it finishes deploying or until a timeout is reached.
    response = queryAllStacks(session, accountName, log)
    # If stacks failed to deploy, update task to error, log and exit
    if (response):
        # Logging
        errorExceptionInfo = "[awsStart | {}] Error AWS stack(s) failed to deploy.".format(
            str(accountName))
        log.error(errorExceptionInfo)
        # DBConnect ============================
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName, errorExceptionInfo)
        # Update task['taskStatus']
        DBConnect.setTaskStatusToError(taskId)
        # ======================================
        # Exit
        return
    # Need to get the stack info now BUT not store it yet as the senson might need to be spun up.
    # If queryStackAndReturnInfo() is called after the sensor is up, it will return the sensor output, so do it now and store it.
    successInfoToAppendToTask = queryStackAndReturnInfo(
        session, taskId, accountName, log)

    # ======
    # Sensor
    # ======

    # Check if a sensor is required
    if (sensor == "yes"):
        # =====================
        # Get Sensor Parameters
        # =====================
        # Get the course['sensorParameters'] from the DBConnect
        courseSensorParameters = DBConnect.returnCourseSensorParameters(
            courseName)

        # Create lists used for each parameted. All of them are sorted by index.
        listOfSensorParamFiles = []
        listOfSensorParamKeys = []
        listOfSensorParamValues = []
        listOfSensorParamTypes = []
        # Processed final values used for the buffer.
        listOfSensorParamValuesProcessed = []

        # =========================
        # Process Sensor Parameters
        # =========================
        # Append all the information about each sensor parameter to lists.
        # All lists are ordered by index
        for param in courseSensorParameters['sensorParameters']:
            listOfSensorParamFiles.append(param['paramFile'])
            listOfSensorParamKeys.append(param['paramKey'])
            listOfSensorParamValues.append(param['paramValue'])
            listOfSensorParamTypes.append(param['paramType'])

        # Now the big part, processing the sensor parameters. This must be done in the awsStart script and not the scheduler.
        # This is done because some parameters require the course cloudFormation to be up and running. (It creates things required for the sensor)
        try:
            # Go through each parameter and process it. The final processed result is appended to 'listOfSensorParamValuesProcessed' (Plugins need to be processed)
            for index in range(len(listOfSensorParamFiles)):
                # There are two types of sensor parameters possible, 'plugin-static' and 'static'
                # -------------
                # plugin-static
                # -------------
                if (listOfSensorParamTypes[index] == "plugin-static"):
                    # Get the paramFile as it is required to process the plugin
                    paramFile = listOfSensorParamFiles[index]
                    # Get the Key of the parameter
                    paramKey = listOfSensorParamKeys[index]
                    # Get the static Value of the parameter stored in DB as it is static
                    paramUnprocessedValue = listOfSensorParamValues[index]
                    # ---
                    # Now run and process the parameter as it is a plugin
                    sensorParamProcessedValue = sensorParameterPluginStatic(
                        paramFile, paramUnprocessedValue, accountName, region)
                    for key in sensorParamProcessedValue:
                        value = sensorParamProcessedValue[key]
                        if (checkParamValueForError(key)):
                            # Logging
                            errorExceptionInfo = "[awsStart | {}] Failed to process plugin parameter: {}. Plugin response: {}".format(
                                str(accountName), str(key), str(value))
                            log.error(errorExceptionInfo)
                            # DBConnect ============================
                            # Update task['errorInfo']
                            DBConnect.appendTaskErrorInfo(
                                taskId, accountName, errorExceptionInfo)
                            # Update task['taskStatus']
                            DBConnect.setTaskStatusToError(taskId)
                            # ======================================
                            # Exit
                            return
                        else:
                            listOfSensorParamValuesProcessed.append(str(value))
                # There are two types of sensor parameters possible, 'plugin-static' and 'static'
                # ------
                # static
                # ------
                elif (listOfSensorParamTypes[index] == "static"):
                    # Append the static param value. No processing required as it is not a plugin
                    listOfSensorParamValuesProcessed.append(
                        str(listOfSensorParamValues[index]))
                # All other types are not supporded for now
                # No other parameter types accapted. Return error
                else:
                    # Logging
                    error = "[awsStart | {}] Sensor parameter Type '{}' not accepted for sensor Parameters.".format(
                        str(accountName), str(listOfSensorParamTypes[index]))
                    log.error(error)
                    # DBConnect ============================
                    # Update task['errorInfo']
                    DBConnect.appendTaskErrorInfo(taskId, accountName, error)
                    # Update task['taskStatus']
                    DBConnect.setTaskStatusToError(taskId)
                    # ======================================
                    # Exit
                    return
        except Exception as e:
            # Logging
            errorExceptionInfo = "[awsStart | {}] Error processing sensor parameters: {}".format(
                str(e))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            # Exit
            return
        # ========================
        # Sensor Parameters Buffer
        # ========================
        # This buffer is passed into 'cloudFormation.create_stack'
        try:
            # The buffer containing all sensorParametersKeys and parametersValsBuffer ready for 'cloudFormation.create_stack'
            parametersBuffer = []
            # Creating the buffer
            for paramIndex in range(len(listOfSensorParamKeys)):
                parametersBuffer.append({
                    'ParameterKey':
                    str(listOfSensorParamKeys[paramIndex]),
                    'ParameterValue':
                    str(listOfSensorParamValuesProcessed[paramIndex])
                })
            # logging
            log.info("[awsStart | {}] Course Parameters Buffer: {}".format(
                str(accountName), str(parametersBuffer)))
        except Exception as e:
            # Logging
            errorExceptionInfo = "[awsStart | {}] Error creating sensor parameters buffer: {}".format(
                str(accountName), str(e))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            # Exit
            return

        # =====================
        # Cloud Formation Stack
        # =====================
        # Creating the cloudFormation stack in AWS using 'cloudFormation.create_stack'
        try:
            cloudFormation.create_stack(StackName="Sensor",
                                        TemplateURL=str(sensorTemplate),
                                        Parameters=parametersBuffer,
                                        Capabilities=['CAPABILITY_NAMED_IAM'])
            # logging
            log.info(
                "[awsStart | {}] starting sensor cloudFormation...".format(
                    str(accountName)))
            # Wait Gary number seconds to give time for AWS to set up stacks. Stack creation will take many minutes anyway
            time.sleep(garyTheSnail)
        except Exception as e:
            # Logging
            errorExceptionInfo = "[awsStart | {}] Error creating AWS stack: {}".format(
                str(accountName), str(e))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            # Exit
            return

        # =====================
        # |Query the AWS Stack|
        # =====================
        # Query the AWS Stack and wait until it finishes deploying or until a timeout is reached.
        response = queryAllStacks(session, accountName, log)
        # If stacks failed to deploy, update task to error, log and exit
        if (response):
            # Logging
            errorExceptionInfo = "[awsStart | {}] Error AWS sensor stack(s) failed to deploy.".format(
                str(accountName))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            # Exit
            return

        # ===============================================================================
        # Adding --protocol all to a security group begining with "Sensor-USM-ServicesSG"
        # ===============================================================================
        response = addProtocolAllToSensorUSMServicesSG(session, accountName,
                                                       log)
        # If adding the security group fails, update task to error, log and exit
        if (response[0]):
            # Logging
            errorExceptionInfo = "[awsStart | {}] Failed to add --protocol all to Sensor-USM-ServicesSG security group. Error: {}".format(
                str(accountName), str(response[1]))
            log.exception(errorExceptionInfo)
            # DBConnect ============================
            # Update task['errorInfo']
            DBConnect.appendTaskErrorInfo(taskId, accountName,
                                          errorExceptionInfo)
            # Update task['taskStatus']
            DBConnect.setTaskStatusToError(taskId)
            # ======================================
            # Exit
            return

        # Add sensor public and private IP's
        successInfoToAppendToTask = appendInternalAndExternalIpsForSuccessInfo(
            session, successInfoToAppendToTask, accountName, log)

        # Add the output information from the cloudFormation to task['successInfo']
        addStackSuccessInfoToTask(session, taskId, accountName,
                                  successInfoToAppendToTask)

        # After the sensor is up, now we can finish the task successfully
        # DBConnect ============================
        # Update task['taskStatus']
        DBConnect.setTaskStatusToReady(taskId)
        # ======================================

    # Jump to here if no sensor is required and mark the task successfully
    else:
        # Add the output information from the cloudFormation to task['successInfo']
        addStackSuccessInfoToTask(session, taskId, accountName,
                                  successInfoToAppendToTask)

        # DBConnect ============================
        # Update task['taskStatus']
        DBConnect.setTaskStatusToReady(taskId)
Ejemplo n.º 3
0
def queryAllStacks(session, accountName, log):
    try:
        # Timeout counter variable
        timeoutCounter = 0
        # Fail flag, set when a task timeouts or has one of the unsuccessful states like: CREATE_FAILED
        failFlag = False
        # Loop until a timeout is reached (will break out of loop)
        while (True):
            # Get all stacks in the account using boto3 session
            allStacks = session.client("cloudformation").list_stacks()
            # Log the loop for something to look at
            log.info("[awsStart | {}] Querying all stacks...".format(
                str(accountName)))
            # Variables
            # 2 lists one for stackNames and other for its status.
            # To successfully exit this function, all stacks in these arrays have to be 'CREATE_COMPLETE'
            stackNames = []
            stackStatuses = []
            # Counter incremented when a stack finished successfully. Compared with list of stackNames in order to exit the function.
            completeStackStatusCounter = 0
            # Loop through all the stacks in 'allStacks'
            for stack in allStacks['StackSummaries']:
                if ((stack['StackStatus'] == 'CREATE_IN_PROGRESS')
                        or (stack['StackStatus'] == 'CREATE_COMPLETE')
                        or (stack['StackStatus'] == 'CREATE_FAILED')
                        or (stack['StackStatus'] == 'ROLLBACK_IN_PROGRESS')
                        or (stack['StackStatus'] == 'ROLLBACK_FAILED')
                        or (stack['StackStatus'] == 'ROLLBACK_COMPLETE')):
                    stackNames.append(str(stack['StackName']))
                    stackStatuses.append(str(stack['StackStatus']))
            # Add +1 to the 'completeStackStatusCounter' when a stack has status of 'CREATE_COMPLETE'
            for stackStatus in stackStatuses:
                # stack success
                if (stackStatus == 'CREATE_COMPLETE'):
                    completeStackStatusCounter += 1
                # stack fail, set the fail flag and break the loop. It's over, a stack failed to deploy
                elif ((stackStatus == 'CREATE_FAILED')
                      or (stackStatus == 'ROLLBACK_IN_PROGRESS')
                      or (stackStatus == 'ROLLBACK_FAILED')
                      or (stackStatus == 'ROLLBACK_COMPLETE')):
                    # mark the fail flag true
                    failFlag = True
                    # DBConnect ============================
                    # Update task['errorInfo']
                    DBConnect.appendTaskErrorInfo(
                        taskId, accountName,
                        "CloudFormation for {} failed to deploy. Log in with Admin and inspect the cloudFormation events."
                        .format(str(accountName)))
                    # Update task['taskStatus']
                    DBConnect.setTaskStatusToError(taskId)
                    # ======================================
                    break
            # Check if all stacks are up successfully
            if (completeStackStatusCounter == len(stackNames)):
                # logging
                log.info("[awsStart | {}] Stacks created.".format(
                    str(accountName)))
                # this will be False, no fail or error
                # Exit function
                return failFlag
            # Add to the timeout counter
            timeoutCounter += 1
            # Check for timeout, exit function if true
            if (timeoutCounter > 60):
                # logging
                log.error(
                    "[awsStart | {}] 60 minute timeout in queryAllStacks method, Timeout error."
                    .format(str(accountName)))
                # mark the fail flag true
                failFlag = True
            # Check if the failFlag is set, if it is, a stack didn't deploy
            if (failFlag):
                # logging
                log.error("[awsStart | {}] Failed to create stack.".format(
                    str(accountName)))
                # this will be True, some error occured or cloudFormation failed to deploy
                return failFlag
            # Sleep and give time for stacks to deploy
            time.sleep(60)
    except Exception as e:
        log.exception(
            "[awsStart | {}] Query All Stacks function failed: {}.".format(
                str(accountName), str(e)))
        return True
Ejemplo n.º 4
0
def main(jsonDoc):

    # ------------
    # Logger setup
    # ------------
    try:
        logging.basicConfig(filename='/var/log/boru.log',
                            level=logging.INFO,
                            format="%(asctime)s: %(levelname)s: %(message)s")
        log = logging.getLogger('SCRIPT_NAME')
    except Exception as e:
        # No logging, just print, can't log :(
        print("[SCRIPT_NAME] Critical Logger Setup Error: {}".format(str(e)))
        # Exit
        return

    # -----------------------------------
    # Extracting the task_id from jsonDoc
    # -----------------------------------
    # Required to use DBConnect, passed into every jsonDoc.
    taskId = jsonDoc['task_id']

    # --------------
    # YOUR CODE HERE
    # --------------

    # --------------------------------------------------------------------------------------------------------------------
    # EXAMPLES BELOW
    # --------------------------------------------------------------------------------------------------------------------

    # ----------------------------------------------------------
    # Example of appending 'ERROR' information using 'DBConnect'
    # ----------------------------------------------------------
    # NOTE: This script MUST update the Task Status to 'Error' or 'Ready' before exiting any script.
    try:
        i = 10 / 0
    except Exception as e:
        # Logging
        errorExceptionInfo = "[SCRIPT_NAME] Example Function Error: {}".format(
            str(e))
        log.exception(errorExceptionInfo)
        # Update task['errorInfo']
        DBConnect.appendTaskErrorInfo(taskId, accountName,
                                      "Error: {}".format(str(e)))
        # Update task['taskStatus'] to 'Error'
        DBConnect.setTaskStatusToError(taskId)
        # Exit
        return

    # ------------------------------------------------------------
    # Example of appending 'SUCCESS' information using 'DBConnect'
    # ------------------------------------------------------------
    # NOTE: This script MUST update the Task Status to 'Ready' or 'Error' before exiting any script.
    # Update task['successInfo']
    DBConnect.appendTaskSuccessInfo(taskId, accountName,
                                    "Successful Info Here")
    # Update task['taskStatus'] to 'Ready'
    DBConnect.setTaskStatusToReady(taskId)
    # Exit
    return

    # --------------------------------------------------------------------------------------------------------------------