Example #1
0
def oscall(cmd, get=False):
    """
    This function performs a OS subprocess call.
    All output is thrown away unless an error has occured or if @get is True
    Arguments:
        @cmd: the string command to run
        [get] : True means return (stdout, stderr)
    Returns:
        None if not @get and no error
        (stdout, retcode, stderr) if @get or yes error
    """
    # Since we are already in a deferred chain, use subprocess to block and make the call to mount right HERE AND NOW
    proc = subprocess.Popen(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    output, errors = proc.communicate()
    if (proc.returncode or get):
        return (output, proc.returncode, errors)
    else:
        if (output and output != ""):
            out.verbose('"%s" stdout: "%s"\n' % (cmd, output.rstrip()))
        if (errors and errors != ""):
            out.verbose('"%s" stderr: "%s"\n' % (cmd, errors.rstrip()))
        return None
Example #2
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    # Generate virt start script, stored in cache (key: 'virtPreamble')
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_PREAMBLE,
                          (dockerconfig.getVirtPreamble, ))

    # Make sure volume directories exist.
    update.plans.addPlans(plangraph.CREATE_VOLUME_DIRS,
                          (dockerconfig.createVolumeDirs, ),
                          (dockerconfig.abortCreateVolumeDirs, ))

    # If the user specifies DHCP then we need to generate the config and store it to disk
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_DHCP,
                          (dhcp.getVirtDHCPSettings, ))
    update.plans.addPlans(plangraph.RUNTIME_SET_VIRT_DHCP,
                          (dhcp.setVirtDHCPSettings, ))

    # Reload configuration files
    todoPlan = (configservice.reloadAll, )
    abtPlan = [(osconfig.revertConfig, "dhcp"),
               (osconfig.revertConfig, "firewall"),
               (osconfig.revertConfig, "network"),
               (osconfig.revertConfig, "wireless"),
               (configservice.reloadAll, )]
    update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG, todoPlan, abtPlan)

    return None
Example #3
0
def executePlans(update):
    """
        Primary function that actually executes all the functions that were added to plans by all
        the exc modules. This function can heavily modify the OS/files/etc.. so the return value is
        very important.
        Returns:
            True in error : abortPlans function should be called
            False otherwise : everything is OK
    """
    out.header('Executing plans %r\n' % (update))
    # Finding the functions to call is actually done by a 'iterator' like function in the plangraph module
    while (True):
        # This function either returns None or a tuple just like generate added to it
        p = update.plans.getNextTodo()

        # No more to do?
        if (not p):
            break

        # Explode tuple otherwise
        func, args = p

        # We are in a try-except block so if func isn't callable that will catch it
        try:
            out.verbose('Calling %s\n' % (func))
            update.progress("Calling {}".format(func.__name__))
            #
            # Call the function from the execution plan
            #
            # args may be empty, but we don't want to pass in a tuple if we don't need to.
            # This below explodes the args so if @args is (), then what is passed is @update
            skipme = func(*((update, ) + args))

        except Exception as e:
            out.exception(e, True)
            # plans = str(update.plans)) # Removed because breaks new out.exception call
            out.warn("Failed to execute plan %s%s" % (func.__name__, args))
            update.responses.append({
                'exception': str(e),
                'traceback': traceback.format_exc()
            })
            update.failure = str(e)
            return True

        # The functions we call here can return other functions, if they do these are functions that should
        # be skipped later on (for instance a set* function discovering it didn't change anything, later on
        # we shouldn't call the corresponding reload function)
        if (skipme):
            # These functions can return individual functions to skip, or a list of multiple functions
            if (not isinstance(skipme, list)):
                skipme = [skipme]

            for skip in skipme:
                out.warn('Identified a skipped function: %r\n' % (skip))
                update.plans.registerSkip(skip)

    # Now we are done
    return False
Example #4
0
def generatePlans(update):
    """
    This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
    then adds Plan() calls to make the Chute match the @newChute.

    Returns:
        True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.ENFORCE_ACCESS_RIGHTS,
                          (security.enforce_access_rights, ))

    return None
Example #5
0
def generatePlans(update):
    out.verbose("%r\n" % (update))

    if update.updateType == "factoryreset":
        update.plans.addPlans(plangraph.STATE_CALL_STOP,
                              (dockerapi.removeAllContainers, ))
        update.plans.addPlans(plangraph.STATE_SAVE_CHUTE,
                              (state.removeAllChutes, ))

    elif update.updateType == "reboot":
        update.plans.addPlans(plangraph.STATE_CALL_STOP, (power.reboot, ))

    elif update.updateType == "shutdown":
        update.plans.addPlans(plangraph.STATE_CALL_STOP, (power.shutdown, ))
Example #6
0
    def delConfig(self, config, options):
        """Finds a match to the config input and removes it from the internal config data structure."""
        config = stringify(config)
        options = stringify(options)

        # Search through the config array for matches
        for i, e in enumerate(self.config):
            c, o = e
            if(c == config and o == options):
                break
        else:
            # Getting here means we didn't break so no match
            out.verbose('No match to delete, config: %r\n' % (config))
            return

        del(self.config[i])
Example #7
0
def abortPlans(update):
    """
        This function should be called if one of the Plan objects throws an Exception.
        It takes the PlanMap argument and calls the getNextAbort function just like executePlans does with todoPlans.
        This dynamically generates an abort plan list based on what plans were originally executed.
        Returns:
            True in error : This is really bad
            False otherwise : we were able to restore system state back to before the executeplans function was called
    """
    out.header('Aborting plans %r\n' % (update.plans))
    sameError = False
    while (True):
        # This function either returns None or a tuple just like generate added to it
        p = update.plans.getNextAbort()

        # No more to do?
        if (not p):
            break

        # Explode tuple otherwise
        func, args = p

        # We are in a try-except block so if func isn't callable that will catch it
        try:
            out.verbose('Calling {}\n'.format(func))
            update.progress('Calling {}'.format(func.__name__))

            func(*((update, ) + args))

            # If the func is called without exception then clear the @sameError flag for the next function call
            sameError = False

        except Exception as e:
            # Since we are running this in an infinite loop if a major function throws an error
            # we could loop forever, so check for the error, which is only reset at the end of the loop
            if (sameError):
                return True
            update.responses.append({
                'exception': str(e),
                'traceback': traceback.format_exc()
            })
            out.fatal('An abort function raised an exception!!! %r: %s\n%s\n' %
                      (update.plans, str(e), traceback.format_exc()))
            sameError = True

    # Getting here we assume the system state has been restored using our abort plan
    return False
Example #8
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.RESOURCE_GET_ALLOCATION,
                          (resource.getResourceAllocation, ))

    update.plans.addPlans(plangraph.RESOURCE_SET_ALLOCATION,
                          (dockerapi.setResourceAllocation, ),
                          (dockerapi.revertResourceAllocation, ))

    return None
Example #9
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    #print any warnings from previous update if they exist
    if hasattr(update,
               'pkg') and update.old != None and update.old.warning != None:
        update.pkg.request.write(update.old.warning + '\n')

    # TODO: Create a directory for the chute for us to hold onto things (dockerfile, OS config stuff)

    return None
Example #10
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.RESOURCE_GET_ALLOCATION,
            (resource.getResourceAllocation,))

    update.plans.addPlans(plangraph.RESOURCE_SET_ALLOCATION,
            (dockerapi.setResourceAllocation,),
            (dockerapi.revertResourceAllocation,))

    return None
Example #11
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    # Check for some error conditions that we can detect during the planning
    # stage, e.g. starting a chute that does not exist.
    if not validate_change(update):
        return True

    update.plans.addPlans(plangraph.STATE_GENERATE_SERVICE_PLANS,
                          (generate_service_plans, ))

    if update.new.isRunning():
        update.plans.addPlans(plangraph.STATE_NET_START,
                              (dockerapi.setup_net_interfaces, ),
                              (dockerapi.cleanup_net_interfaces, ))

        if update.old is None:
            update.plans.addPlans(plangraph.STATE_CREATE_BRIDGE,
                                  (dockerapi.create_bridge, ),
                                  (dockerapi.remove_bridge, ))

    if update.old is not None and update.old.isRunning():
        update.plans.addPlans(plangraph.STATE_NET_STOP,
                              (dockerapi.cleanup_net_interfaces, ),
                              (dockerapi.setup_net_interfaces, ))

    if update.updateType == "delete":
        update.plans.addPlans(plangraph.STATE_REMOVE_BRIDGE,
                              (dockerapi.remove_bridge, ),
                              (dockerapi.create_bridge, ))

    # Save the chute to the chutestorage.
    update.plans.addPlans(plangraph.STATE_SAVE_CHUTE, (state.saveChute, ),
                          (state.revertChute, ))

    return None
Example #12
0
def abortPlans(update):
    """
        This function should be called if one of the Plan objects throws an Exception.
        It takes the PlanMap argument and calls the getNextAbort function just like executePlans does with todoPlans.
        This dynamically generates an abort plan list based on what plans were originally executed.
        Returns:
            True in error : This is really bad
            False otherwise : we were able to restore system state back to before the executeplans function was called
    """
    out.header('Aborting plans %r\n' % (update.plans))
    sameError = False
    while(True):
        # This function either returns None or a tuple just like generate added to it
        p = update.plans.getNextAbort()

        # No more to do?
        if(not p):
            break

        # Explode tuple otherwise
        func, args = p

        # We are in a try-except block so if func isn't callable that will catch it
        try:
            out.verbose('Calling {}\n'.format(func))
            update.progress('Calling {}'.format(func.__name__))

            func(*((update, ) + args))

            # If the func is called without exception then clear the @sameError flag for the next function call
            sameError = False

        except Exception as e:
            # Since we are running this in an infinite loop if a major function throws an error
            # we could loop forever, so check for the error, which is only reset at the end of the loop
            if(sameError):
                return True
            update.responses.append({'exception': str(e), 'traceback': traceback.format_exc()})
            out.fatal('An abort function raised an exception!!! %r: %s\n%s\n' % (update.plans, str(e), traceback.format_exc()))
            sameError = True

    # Getting here we assume the system state has been restored using our abort plan
    return False
Example #13
0
    def execute(self):
        try:
            proc = subprocess.Popen(self.command, stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)
            self.pid = proc.pid
            for line in proc.stdout:
                out.verbose("{} {}: {}".format(self.command[0], self.pid, line))
            for line in proc.stderr:
                out.verbose("{} {}: {}".format(self.command[0], self.pid, line))
            self.result = proc.wait()
            out.info('Command "{}" returned {}\n'.format(
                     " ".join(self.command), self.result))
        except Exception as e:
            out.info('Command "{}" raised exception {}\n'.format(
                     " ".join(self.command), e))
            self.result = e

        if self.parent is not None:
            self.parent.executed.append(self)

        return (self.ignoreFailure or self.result == 0)
Example #14
0
    def execute(self):
        try:
            proc = subprocess.Popen(self.command, stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)
            self.pid = proc.pid
            for line in proc.stdout:
                out.verbose("{} {}: {}".format(self.command[0], self.pid, line))
            for line in proc.stderr:
                out.verbose("{} {}: {}".format(self.command[0], self.pid, line))
            self.result = proc.wait()
            if self.result == 0:
                out.verbose('Command "{}" returned {}\n'.format(
                         " ".join(self.command), self.result))
            else:
                out.info('Command "{}" returned {}\n'.format(
                         " ".join(self.command), self.result))
        except Exception as e:
            out.info('Command "{}" raised exception {}\n'.format(
                     " ".join(self.command), e))
            self.result = e

        if self.parent is not None:
            self.parent.executed.append(self)

        return (self.ignoreFailure or self.result == 0)
Example #15
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    # Generate virt start script, stored in cache (key: 'virtPreamble')
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_PREAMBLE,
                          (dockerconfig.getVirtPreamble, ))

    # Make sure volume directories exist.
    update.plans.addPlans(plangraph.CREATE_VOLUME_DIRS,
                          (dockerconfig.createVolumeDirs, ),
                          (dockerconfig.abortCreateVolumeDirs, ))

    # If the user specifies DHCP then we need to generate the config and store it to disk
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_DHCP,
                          (dhcp.getVirtDHCPSettings, ))

    todoPlan = (dhcp.setVirtDHCPSettings, )
    abtPlan = (dhcp.revert_dhcp_settings, )
    update.plans.addPlans(plangraph.RUNTIME_SET_VIRT_DHCP, todoPlan, abtPlan)

    # Reload configuration files
    todoPlan = (configservice.reloadAll, )
    update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG, todoPlan)

    # Reload configuration files if aborting.  This needs to happen at the
    # right place in the update pipeline such that UCI files have been
    # restored to their previous contents.
    todoPlan = (configservice.reload_placeholder, )
    abtPlan = (configservice.reloadAll, )
    update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG_BACKOUT, todoPlan,
                          abtPlan)

    return None
Example #16
0
    def onChallenge(self, challenge):
        if challenge.method == u"wampcra":
            out.verbose("WAMP-CRA challenge received: {}".format(challenge))

            wampPassword = nexus.core.getKey('apitoken')
            if u'salt' in challenge.extra:
                # salted secret
                key = auth.derive_key(wampPassword, challenge.extra['salt'],
                                      challenge.extra['iterations'],
                                      challenge.extra['keylen'])
            else:
                # plain, unsalted secret
                key = wampPassword

            # compute signature for challenge, using the key
            signature = auth.compute_wcs(key, challenge.extra['challenge'])

            # return the signature to the router for verification
            return signature

        else:
            raise Exception("Invalid authmethod {}".format(challenge.method))
Example #17
0
    def onChallenge(self, challenge):
        if challenge.method == u"wampcra":
            out.verbose("WAMP-CRA challenge received: {}".format(challenge))

            wampPassword = nexus.core.getKey('apitoken')
            if u'salt' in challenge.extra:
                # salted secret
                key = auth.derive_key(wampPassword,
                                      challenge.extra['salt'],
                                      challenge.extra['iterations'],
                                      challenge.extra['keylen'])
            else:
                # plain, unsalted secret
                key = wampPassword

            # compute signature for challenge, using the key
            signature = auth.compute_wcs(key, challenge.extra['challenge'])

            # return the signature to the router for verification
            return signature

        else:
            raise Exception("Invalid authmethod {}".format(challenge.method))
Example #18
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    # Generate virt start script, stored in cache (key: 'virtPreamble')
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_PREAMBLE, (dockerconfig.getVirtPreamble, ))

    # Make sure volume directories exist.
    update.plans.addPlans(plangraph.CREATE_VOLUME_DIRS,
            (dockerconfig.createVolumeDirs, ),
            (dockerconfig.abortCreateVolumeDirs, ))

    # If the user specifies DHCP then we need to generate the config and store it to disk
    update.plans.addPlans(plangraph.RUNTIME_GET_VIRT_DHCP, (dhcp.getVirtDHCPSettings, ))

    todoPlan = (dhcp.setVirtDHCPSettings, )
    abtPlan = (dhcp.revert_dhcp_settings, )
    update.plans.addPlans(plangraph.RUNTIME_SET_VIRT_DHCP, todoPlan, abtPlan)

    # Reload configuration files
    todoPlan = (configservice.reloadAll, )
    update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG, todoPlan)

    # Reload configuration files if aborting.  This needs to happen at the
    # right place in the update pipeline such that UCI files have been
    # restored to their previous contents.
    todoPlan = (configservice.reload_placeholder, )
    abtPlan = (configservice.reloadAll, )
    update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG_BACKOUT, todoPlan, abtPlan)

    return None
Example #19
0
def generatePlans(update):
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.SNAP_INSTALL, (config.snap.updateSnap, ))
Example #20
0
def executePlans(update):
    """
        Primary function that actually executes all the functions that were added to plans by all
        the exc modules. This function can heavily modify the OS/files/etc.. so the return value is
        very important.
        Returns:
            True in error : abortPlans function should be called
            False otherwise : everything is OK
    """
    out.header('Executing plans %r\n' % (update))
    # Finding the functions to call is actually done by a 'iterator' like function in the plangraph module
    while(True):
        # This function either returns None or a tuple just like generate added to it
        p = update.plans.getNextTodo()

        # No more to do?
        if(not p):
            break

        # Explode tuple otherwise
        func, args = p

        # We are in a try-except block so if func isn't callable that will catch it
        try:
            out.verbose('Calling %s\n' % (func))
            update.progress("Calling {}".format(func.__name__))
            #
            # Call the function from the execution plan
            #
            # args may be empty, but we don't want to pass in a tuple if we don't need to.
            # This below explodes the args so if @args is (), then what is passed is @update
            skipme = func(*((update, ) + args))

        except Exception as e:
            out.exception(e, True)
            # plans = str(update.plans)) # Removed because breaks new out.exception call
            out.warn("Failed to execute plan %s%s" % (func.__name__, args))
            update.responses.append({'exception': str(e), 'traceback': traceback.format_exc()})
            update.failure = str(e)
            return True

        # The functions we call here can return other functions, if they do
        # these are functions that should be skipped later on (for instance a
        # set* function discovering it didn't change anything, later on we
        # shouldn't call the corresponding reload function)
        if skipme is not None:
            # If the function returned a Deferred, we will drop out of the
            # execution pipeline and resume later.
            if isinstance(skipme, Deferred):
                out.verbose('Function {} returned a Deferred'.format(func))
                return skipme

            # These functions can return individual functions to skip, or a
            # list of multiple functions
            elif callable(skipme):
                skipme = [skipme]

            for skip in skipme:
                out.warn('Identified a skipped function: %r\n' % (skip))
                update.plans.registerSkip(skip)

    # Now we are done
    return False
Example #21
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    if update.updateType in ['create', 'update']:
        update.plans.addPlans(plangraph.STATE_BUILD_IMAGE,
                              (dockerapi.buildImage, ),
                              (dockerapi.removeNewImage, ))

    # If this chute is new (no old version)
    if (update.old is None):
        out.verbose('new chute\n')

        # If it's a stop, start, delete, or restart command go ahead and fail right now since we don't have a record of it
        if update.updateType in ['stop', 'start', 'delete', 'restart']:
            update.failure = "No chute found with id: " + update.name
            return True
        # If we are now running then everything has to be setup for the first time
        if (update.new.state == Chute.STATE_RUNNING):
            update.plans.addPlans(plangraph.STATE_CALL_START,
                                  (dockerapi.startChute, ),
                                  (dockerapi.removeNewContainer, ))

        # Check if the state is invalid, we should return bad things in this case (don't do anything)
        elif (update.new.state == Chute.STATE_INVALID):
            if (settings.DEBUG_MODE):
                update.responses.append('Chute state is invalid')
            return True

    # Not a new chute
    else:
        if update.updateType == 'start':
            if update.old.state == Chute.STATE_RUNNING:
                update.failure = update.name + " already running."
                return True
            update.plans.addPlans(plangraph.STATE_CALL_START,
                                  (dockerapi.restartChute, ))
        elif update.updateType == 'restart':
            update.plans.addPlans(plangraph.STATE_CALL_STOP,
                                  (dockerapi.removeOldContainer, ),
                                  (dockerapi.startOldContainer, ))
            update.plans.addPlans(plangraph.STATE_CALL_START,
                                  (dockerapi.startChute, ),
                                  (dockerapi.removeNewContainer, ))
        elif update.updateType == 'create':
            update.failure = update.name + " already exists on this device."
            return True
        elif update.updateType == 'update':
            if update.new.version == update.old.version:
                update.failure = "Version {} already exists on this device.".format(
                    update.new.version)
                return True
            elif (update.new.version <
                  update.old.version) and settings.REJECT_DOWNGRADE:
                update.failure = "A newer version ({}) already exists on this device.".format(
                    update.old.version)
                return True
            else:
                update.plans.addPlans(plangraph.STATE_CALL_STOP,
                                      (dockerapi.removeOldContainer, ),
                                      (dockerapi.startOldContainer, ))
                update.plans.addPlans(plangraph.STATE_CALL_START,
                                      (dockerapi.startChute, ),
                                      (dockerapi.removeNewContainer, ))
                update.plans.addPlans(plangraph.STATE_CALL_CLEANUP,
                                      (dockerapi.removeOldImage, ))
        elif update.new.state == Chute.STATE_STOPPED:
            if update.updateType == 'delete':
                update.plans.addPlans(plangraph.STATE_CALL_STOP,
                                      (dockerapi.removeChute, ))
            if update.updateType == 'stop':
                if update.old.state == Chute.STATE_STOPPED:
                    update.failure = update.name + " already stopped."
                    return True
                update.plans.addPlans(plangraph.STATE_CALL_STOP,
                                      (dockerapi.stopChute, ))

    # Save the chute to the chutestorage.
    update.plans.addPlans(plangraph.STATE_SAVE_CHUTE, (state.saveChute, ),
                          (state.revertChute, ))

    return None
Example #22
0
def generatePlans(update):
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.SNAP_INSTALL,
                          (snap.updateSnap, ))
Example #23
0
def generatePlans(update):
    out.verbose("%r\n" % (update))

    # Detect system devices and set up basic configuration for them (WAN
    # interface, wireless devices).  These steps do not need to be reverted on
    # abort.
    #
    # checkSystemDevices may reboot the machine if expected devices are
    # missing.
    #
    # abortNetworkConfig is added as an abort command here so that it runs when
    # config.network.getNetworkConfig or just about anything else fails.
    #
    # reloadAll is added as an abort command here so that it runs when any of
    # the set* plans fail and back out.
    update.plans.addPlans(plangraph.STRUCT_GET_SYSTEM_DEVICES,
                          (devices.getSystemDevices, ),
                          (network.abortNetworkConfig, ))
    update.plans.addPlans(plangraph.CHECK_SYSTEM_DEVICES,
                          (devices.checkSystemDevices, ))

    update.plans.addPlans(plangraph.STRUCT_GET_RESERVATIONS,
                          (reservations.getReservations, ))

    update.plans.addPlans(plangraph.STRUCT_GET_HOST_CONFIG,
                          (hostconfig.getHostConfig, ))

    # Save current network configuration into chute cache (key: 'networkInterfaces')
    update.plans.addPlans(plangraph.STRUCT_GET_INT_NETWORK,
                          (network.getNetworkConfig, ))

    # Start haproxy.  This does not depend on the host config, and we want
    # it setup even in cases where applying the host config failed.
    update.plans.addPlans(plangraph.RECONFIGURE_PROXY,
                          (haproxy.reconfigureProxy, ))

    if update.updateType in CONFIG_CHANGING_TYPES:
        # Save current host configuration to disk.
        update.plans.addPlans(plangraph.STRUCT_SET_HOST_CONFIG,
                              (hostconfig.setHostConfig, ),
                              (hostconfig.revertHostConfig, ))

        # Apply host configuration to system configuration.
        update.plans.addPlans(plangraph.STRUCT_SET_SYSTEM_DEVICES,
                              (devices.setSystemDevices, ),
                              (configservice.reloadAll, ))

        # Apply zerotier configuration.
        update.plans.addPlans(plangraph.ZEROTIER_CONFIGURE,
                              (zerotier.configure, ))

        # Apply Airshark configuration.
        update.plans.addPlans(plangraph.AIRSHARK_CONFIGURE,
                              (airshark.configure, ))

        # Configure telemetry service.
        update.plans.addPlans(plangraph.TELEMETRY_SERVICE,
                              (services.configure_telemetry, ))

        # Reload configuration files
        todoPlan = (configservice.reloadAll, )
        update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG, todoPlan)

        # Reload configuration files if aborting.  This needs to happen at the
        # right place in the update pipeline such that UCI files have been
        # restored to their previous contents.
        todoPlan = (configservice.reload_placeholder, )
        abtPlan = (configservice.reloadAll, )
        update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG_BACKOUT,
                              todoPlan, abtPlan)
Example #24
0
def generatePlans(update):
    """
        This function looks at a diff of the current Chute (in @chuteStor) and the @newChute,
        then adds Plan() calls to make the Chute match the @newChute.

        Returns:
            True: abort the plan generation process
    """
    out.verbose("%r\n" % (update))

    update.plans.addPlans(plangraph.DOWNLOAD_CHUTE_FILES,
                          (files.download_chute_files, ),
                          (files.delete_chute_files, ))

    update.plans.addPlans(plangraph.LOAD_CHUTE_CONFIGURATION,
                          (files.load_chute_configuration, ))

    # Detect system devices and set up basic configuration for them (WAN
    # interface, wireless devices).  These steps do not need to be reverted on
    # abort.
    #
    # abortNetworkConfig is added as an abort command here so that it runs when
    # config.network.getNetworkConfig or just about anything else fails.
    update.plans.addPlans(plangraph.STRUCT_GET_SYSTEM_DEVICES,
                          (devices.getSystemDevices, ),
                          (network.abortNetworkConfig, ))

    update.plans.addPlans(plangraph.STRUCT_GET_RESERVATIONS,
                          (reservations.getReservations, ))

    update.plans.addPlans(plangraph.STRUCT_GET_HOST_CONFIG,
                          (hostconfig.getHostConfig, ))
    update.plans.addPlans(plangraph.STRUCT_SET_HOST_CONFIG,
                          (hostconfig.setHostConfig, ),
                          (hostconfig.revertHostConfig, ))

    # Save current network configuration into chute cache (key: 'networkInterfaces')
    update.plans.addPlans(plangraph.STRUCT_GET_INT_NETWORK,
                          (network.getNetworkConfig, ))

    # Setup changes to push into OS config files (key: 'osNetworkConfig')
    update.plans.addPlans(plangraph.STRUCT_GET_OS_NETWORK, (network.getOSNetworkConfig, ))

    # Setup changes to push into OS config files (key: 'osWirelessConfig')
    update.plans.addPlans(plangraph.STRUCT_GET_OS_WIRELESS, (wifi.getOSWirelessConfig, ))

    # Changes for networking
    todoPlan = (network.setOSNetworkConfig, )
    abtPlan = (network.revert_os_network_config, )
    update.plans.addPlans(plangraph.STRUCT_SET_OS_NETWORK, todoPlan, abtPlan)

    # Changes for wifi
    todoPlan = (wifi.setOSWirelessConfig, )
    abtPlan = (wifi.revert_os_wireless_config, )
    update.plans.addPlans(plangraph.STRUCT_SET_OS_WIRELESS, todoPlan, abtPlan)

    # Layer 3 bridging support
    todoPlan = (network.getL3BridgeConfig, )
    update.plans.addPlans(plangraph.STRUCT_GET_L3BRIDGE_CONFIG, todoPlan)

    todoPlan = (network.setL3BridgeConfig, )
    abtPlan = (network.revert_l3_bridge_config, )
    update.plans.addPlans(plangraph.STRUCT_SET_L3BRIDGE_CONFIG, todoPlan, abtPlan)

    return None
Example #25
0
def generatePlans(update):
    out.verbose("%r\n" % (update))

    # Detect system devices and set up basic configuration for them (WAN
    # interface, wireless devices).  These steps do not need to be reverted on
    # abort.
    #
    # checkSystemDevices may reboot the machine if expected devices are
    # missing.
    #
    # abortNetworkConfig is added as an abort command here so that it runs when
    # config.network.getNetworkConfig or just about anything else fails.
    #
    # reloadAll is added as an abort command here so that it runs when any of
    # the set* plans fail and back out.
    update.plans.addPlans(plangraph.STRUCT_GET_SYSTEM_DEVICES,
                          (devices.getSystemDevices, ),
                          (network.abortNetworkConfig, ))
    update.plans.addPlans(plangraph.CHECK_SYSTEM_DEVICES,
                          (devices.checkSystemDevices, ))

    update.plans.addPlans(plangraph.STRUCT_GET_RESERVATIONS,
                          (reservations.getReservations, ))

    update.plans.addPlans(plangraph.STRUCT_GET_HOST_CONFIG,
                          (hostconfig.getHostConfig, ))

    # Save current network configuration into chute cache (key: 'networkInterfaces')
    update.plans.addPlans(plangraph.STRUCT_GET_INT_NETWORK,
                          (network.getNetworkConfig, ))

    # Start haproxy.  This does not depend on the host config, and we want
    # it setup even in cases where applying the host config failed.
    update.plans.addPlans(plangraph.RECONFIGURE_PROXY,
                          (haproxy.reconfigureProxy, ))

    if update.updateType in CONFIG_CHANGING_TYPES:
        # Save current host configuration to disk.
        update.plans.addPlans(plangraph.STRUCT_SET_HOST_CONFIG,
                              (hostconfig.setHostConfig, ),
                              (hostconfig.revertHostConfig, ))

        # Apply host configuration to system configuration.
        update.plans.addPlans(plangraph.STRUCT_SET_SYSTEM_DEVICES,
                              (devices.setSystemDevices, ),
                              (configservice.reloadAll, ))

        # Apply zerotier configuration.
        update.plans.addPlans(plangraph.ZEROTIER_CONFIGURE,
                              (zerotier.configure, ))

        # Apply Airshark configuration.
        update.plans.addPlans(plangraph.AIRSHARK_CONFIGURE,
                              (airshark.configure, ))

        # Configure telemetry service.
        update.plans.addPlans(plangraph.TELEMETRY_SERVICE,
                              (services.configure_telemetry, ))

        # Reload configuration files
        todoPlan = (configservice.reloadAll, )
        update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG, todoPlan)

        # Reload configuration files if aborting.  This needs to happen at the
        # right place in the update pipeline such that UCI files have been
        # restored to their previous contents.
        todoPlan = (configservice.reload_placeholder, )
        abtPlan = (configservice.reloadAll, )
        update.plans.addPlans(plangraph.RUNTIME_RELOAD_CONFIG_BACKOUT, todoPlan, abtPlan)