예제 #1
0
    def sshKeys(self, request, user):
        """
        Manage list of authorized keys for SSH access.
        """
        cors.config_cors(request)
        request.setHeader('Content-Type', 'application/json')

        if request.method == "GET":
            try:
                if GovernorClient.isAvailable():
                    client = GovernorClient()
                    keys = client.listAuthorizedKeys(user)
                else:
                    keys = ssh_keys.getAuthorizedKeys(user)
                return json.dumps(keys)
            except Exception as e:
                out.warn(str(e))
                request.setResponseCode(404)
                return json.dumps({'message': str(e)})
        else:
            body = str2json(request.content.read())
            key = body['key'].strip()

            try:
                if GovernorClient.isAvailable():
                    client = GovernorClient()
                    client.addAuthorizedKey(key, user)
                else:
                    ssh_keys.addAuthorizedKey(key, user)
                return json.dumps(body)
            except Exception as e:
                out.warn(str(e))
                request.setResponseCode(404)
                return json.dumps({'message': str(e)})
예제 #2
0
    def update_hostconfig(self, request):
        """
        Replace the device's host configuration.

        **Example request**:

        .. sourcecode:: http

           PUT /api/v1/config/hostconfig
           Content-Type: application/json

           {
             "firewall": {
               "defaults": {
                 "forward": "ACCEPT",
                 "input": "ACCEPT",
                 "output": "ACCEPT"
               }
             },
             ...
           }

        **Example response**:

        .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

           {
             change_id: 1
           }

        For a complete example, please see the Host Configuration section.
        """
        cors.config_cors(request)
        body = str2json(request.content.read())
        config = body['config']

        update = dict(updateClass='ROUTER',
                      updateType='sethostconfig',
                      name=constants.RESERVED_CHUTE_NAME,
                      tok=timeint(),
                      hostconfig=config)

        # We will return the change ID to the caller for tracking and log
        # retrieval.
        update['change_id'] = self.update_manager.assign_change_id()

        self.update_manager.add_update(**update)

        result = {'change_id': update['change_id']}
        request.setHeader('Content-Type', 'application/json')
        return json.dumps(result)
예제 #3
0
def reloadChutes():
    """
    Get update objects to chutes that should be running at startup.

    This function is called to restart any chutes that were running
    prior to the system being restarted.  It waits for pdconfd to
    come up and report whether or not it failed to bring up any of the
    interfaces that existed before the power cycle. If pdconfd indicates
    something failed we then force a stop update in order to bring down
    all interfaces associated with that chute and mark it with a warning.
    If the stop fails we mark the chute with a warning manually and change
    its state to stopped and save to storage this isn't great as it could
    mean our system still has interfaces up associated with that chute.
    If pdconfd doesn't report failure we attempt to start the chute and
    if this fails we trust the abort process to restore the system to a
    consistent state and we manually mark the chute as stopped and add
    a warning to it.

    :returns: (list) A list of UpdateChute objects that should be run
              before accepting new updates.
    """
    if not settings.PDCONFD_ENABLED:
        return []
    chuteStore = ChuteStorage()
    chutes = [ch for ch in chuteStore.getChuteList() if ch.isRunning()]

    # Part of restoring the chute to its previously running state is reclaiming
    # IP addresses, interface names, etc. that it had previously.
    for chute in chutes:
        reclaimNetworkResources(chute)

    #We need to make sure confd is up and all interfaces have been brought up properly
    confdup = False
    while not confdup:
        confdInfo = waitSystemUp()
        if confdInfo == None:
            time.sleep(1)
            continue
        confdup = True
        confdInfo = str2json(confdInfo)

    #Remove any chutes from the restart queue if confd failed to bring up the
    #proper interfaces
    #
    # At this point, we only care about the chute names, not the full objects.
    # We are using sets of chute names for their O(1) membership test and
    # element uniqueness.
    okChutes = set([ch.name for ch in chutes])
    failedChutes = set()
    for iface in confdInfo:
        if iface.get('success') is False:
            failedChuteName = iface.get('comment')
            if failedChuteName == constants.RESERVED_CHUTE_NAME:
                out.warn('Failed to load a system config section')
            elif failedChuteName in okChutes:
                # This was a chute that we are supposed to restart, but one of
                # its config sections failed to load.
                okChutes.remove(failedChuteName)
                failedChutes.add(failedChuteName)
            elif failedChuteName not in failedChutes:
                # In this case, the name in the comment was not something that
                # we recognize from the chute storage.  Maybe the chute storage
                # file was deleted but not the config files, or someone
                # manually modified the config files.  Anyway, we cannot
                # attempt to stop this chute because the object does not exist,
                # but we can give a warning message.
                out.warn('Failed to load config section for '
                         'unrecognized chute: {}'.format(failedChuteName))

    updates = []

    # There was code here that looped over the failedChutes set and explicitly
    # stopped those chutes.  However, if the cause of the failure was
    # transient, those chutes would remain stopped until manually restarted.
    # It seems better to leave them alone so that we try again next time the
    # system reboots.
    #
    # TODO: We should still record the failure somewhere.

    # Only try to restart the chutes that had no problems during pdconf
    # initialization.
    for ch in okChutes:
        update_spec = dict(updateClass='CHUTE',
                           updateType='restart',
                           name=ch,
                           tok=timeint(),
                           func=updateStatus,
                           user=User.get_internal_user())
        update = UpdateChute(update_spec, reuse_existing=True)
        updates.append(update)

    return updates
예제 #4
0
    def provision(self, request):
        """
        Provision the device with credentials from a cloud controller.
        """
        cors.config_cors(request)
        body = str2json(request.content.read())
        routerId = body['routerId']
        apitoken = body['apitoken']
        pdserver = body['pdserver']
        wampRouter = body['wampRouter']

        changed = False
        if routerId != nexus.core.info.pdid \
            or pdserver != nexus.core.info.pdserver \
            or wampRouter != nexus.core.info.wampRouter:
            if pdserver and wampRouter:
                nexus.core.provision(routerId, pdserver, wampRouter)
            else:
                nexus.core.provision(routerId)
            changed = True

        if apitoken != nexus.core.getKey('apitoken'):
            nexus.core.saveKey(apitoken, 'apitoken')
            changed = True

        if changed:
            PDServerRequest.resetToken()
            nexus.core.jwt_valid = False

            def set_update_fetcher(session):
                session.set_update_fetcher(self.update_fetcher)

            @inlineCallbacks
            def start_polling(result):
                yield self.update_fetcher.start_polling()

            def send_response(result):
                response = dict()
                response['provisioned'] = True
                response['httpConnected'] = nexus.core.jwt_valid
                response['wampConnected'] = nexus.core.wamp_connected
                request.setHeader('Content-Type', 'application/json')
                return json.dumps(response)

            wampDeferred = nexus.core.connect(WampSession)
            wampDeferred.addCallback(set_update_fetcher)

            httpDeferred = sendStateReport()
            httpDeferred.addCallback(start_polling)

            identDeferred = sendNodeIdentity()

            dl = DeferredList([wampDeferred, httpDeferred, identDeferred],
                              consumeErrors=True)
            dl.addBoth(send_response)
            reactor.callLater(6, dl.cancel)
            return dl
        else:
            return json.dumps({
                'success':
                False,
                'message':
                'No change on the provision parameters'
            })