def test_get_station(self, ChuteStorage, Popen):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }

        proc = MagicMock()
        Popen.return_value = proc
        proc.stdout = [
            "Station 12:34:56:78:9a:bc (on wlan0)",
            "	inactive time:  304 ms",
            "	rx bytes:       18816",
            "	rx packets:     75",
            "	tx bytes:       5386",
            "	tx packets:     21",
            "	signal:         -29 dBm",
            "	tx bitrate:     54.0 MBit/s"
        ]

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.get_station(request, self.chute.name,
                self.interface['name'], '12:34:56:78:9a:bc')
        station = json.loads(result)
        assert station['mac_addr'] == '12:34:56:78:9a:bc'
        assert station['rx_bytes'] == '18816'
        assert station['signal'] == '-29 dBm'
        assert station['tx_bitrate'] == '54.0 MBit/s'
def test_ChuteApi_operations():
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    body = {
        'config': {}
    }

    request = MagicMock()
    request.content.read.return_value = json.dumps(body)
    request.user = User.get_internal_user()

    functions = [
        api.update_chute,
        api.stop_chute,
        api.start_chute,
        api.restart_chute,
        api.delete_chute
    ]
    for func in functions:
        print("Calling ChuteApi {}".format(func.__name__))

        data = func(request, "test")
        assert isinstance(data, basestring)

        result = json.loads(data)
        assert result['change_id'] == 1
def test_ChuteApi_get_chute(ChuteStorage, ChuteContainer):
    update_manager = MagicMock()
    api = chute_api.ChuteApi(update_manager)

    request = MagicMock()
    request.user = User.get_internal_user()

    container = MagicMock()
    container.getStatus.return_value = "running"
    ChuteContainer.return_value = container

    chute = MagicMock()
    chute.name = "test"
    chute.state = "running"
    chute.version = 5
    chute.environment = {}
    chute.resources = {}

    ChuteStorage.chuteList = {
        "test": chute
    }

    data = api.get_chute(request, chute.name)
    assert isinstance(data, basestring)

    result = json.loads(data)
    assert result['name'] == chute.name
    assert result['version'] == chute.version
def test_ChuteApi_get_network(ChuteStorage):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    iface = {
        'name': 'vwlan0',
        'type': 'wifi',
        'internalIntf': 'wlan0'
    }

    chute = Chute(name="test")
    chute.setCache("networkInterfaces", [iface])

    ChuteStorage.chuteList = {
        "test": chute
    }

    request = MagicMock()
    request.user = User.get_internal_user()

    result = api.get_network(request, "test", "nomatch")
    assert result == "{}"

    result = api.get_network(request, "test", "vwlan0")
    data = json.loads(result)
    assert data['name'] == iface['name']
    assert data['type'] == iface['type']
    assert data['interface'] == iface['internalIntf']
def test_ChuteApi_get_chute(ChuteStorage, ChuteContainer):
    update_manager = MagicMock()
    api = chute_api.ChuteApi(update_manager)

    request = MagicMock()
    request.user = User.get_internal_user()

    container = MagicMock()
    container.getStatus.return_value = "running"
    ChuteContainer.return_value = container

    chute = MagicMock()
    chute.name = "test"
    chute.version = 5
    chute.environment = {}
    chute.resources = {}

    ChuteStorage.chuteList = {"test": chute}

    data = api.get_chute(request, chute.name)
    assert isinstance(data, basestring)

    result = json.loads(data)
    assert result['name'] == chute.name
    assert result['version'] == chute.version
    def test_set_chute_config(self, ChuteStorage):
        ChuteStorage.chuteList = {self.chute.name: self.chute}

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.set_chute_config(request, self.chute.name)
        change = json.loads(result)
        assert change['change_id'] == 1
    def test_hostapd_control(self, ChuteStorage, WebSocketResource):
        ChuteStorage.chuteList = {self.chute.name: self.chute}

        request = MagicMock()
        request.user = User.get_internal_user()

        self.api.hostapd_control(request, self.chute.name,
                                 self.interface['name'])
        WebSocketResource.assert_called()
    def test_get_ssid(self, ChuteStorage, execute):
        ChuteStorage.chuteList = {self.chute.name: self.chute}
        execute.return_value = "OK"

        request = MagicMock()
        request.user = User.get_internal_user()
        result = self.api.get_ssid(request, self.chute.name,
                                   self.interface['name'])
        assert result == "OK"
    def test_get_ssid(self, ChuteStorage, execute):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }
        execute.return_value = "OK"

        request = MagicMock()
        request.user = User.get_internal_user()
        result = self.api.get_ssid(request, self.chute.name, self.interface['name'])
        assert result == "OK"
Beispiel #10
0
    def test_hostapd_control(self, ChuteStorage, WebSocketResource):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }

        request = MagicMock()
        request.user = User.get_internal_user()

        self.api.hostapd_control(request, self.chute.name,
                self.interface['name'])
        WebSocketResource.assert_called()
Beispiel #11
0
    def test_set_chute_config(self, ChuteStorage):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.set_chute_config(request, self.chute.name)
        change = json.loads(result)
        assert change['change_id'] == 1
    def test_get_leases(self, ChuteStorage):
        ChuteStorage.chuteList = {self.chute.name: self.chute}

        request = MagicMock()
        request.user = User.get_internal_user()

        with open("/tmp/dnsmasq-testing.leases", "w") as output:
            output.write("1512058246 00:0d:b9:40:30:80 10.42.0.213 * *")

        result = self.api.get_leases(request, "test", "testing")
        leases = json.loads(result)
        assert len(leases) == 1
        assert leases[0]['mac_addr'] == "00:0d:b9:40:30:80"
        assert leases[0]['ip_addr'] == "10.42.0.213"
Beispiel #13
0
    def test_get_leases(self, ChuteStorage):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }

        request = MagicMock()
        request.user = User.get_internal_user()

        with open("/tmp/dnsmasq-testing.leases", "w") as output:
            output.write("1512058246 00:0d:b9:40:30:80 10.42.0.213 * *")

        result = self.api.get_leases(request, "test", "testing")
        leases = json.loads(result)
        assert len(leases) == 1
        assert leases[0]['mac_addr'] == "00:0d:b9:40:30:80"
        assert leases[0]['ip_addr'] == "10.42.0.213"
    def test_delete_station(self, ChuteStorage, Popen):
        ChuteStorage.chuteList = {self.chute.name: self.chute}

        proc = MagicMock()
        Popen.return_value = proc
        proc.stdout = ["OK"]

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.delete_station(request, self.chute.name,
                                         self.interface['name'],
                                         '12:34:56:78:9a:bc')
        messages = json.loads(result)
        assert len(messages) == 1
        assert messages[0] == "OK"
def test_ChuteApi_get_chute_cache(ChuteStorage):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    chute = MagicMock()
    chute.getCacheContents.return_value = {}

    ChuteStorage.chuteList = {"test": chute}

    request = MagicMock()
    request.user = User.get_internal_user()

    result = api.get_chute_cache(request, "test")
    assert result == "{}"
Beispiel #16
0
def test_ChuteApi_get_chute_cache(ChuteStorage):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    chute = MagicMock()
    chute.getCacheContents.return_value = {}

    ChuteStorage.chuteList = {
        "test": chute
    }

    request = MagicMock()
    request.user = User.get_internal_user()

    result = api.get_chute_cache(request, "test")
    assert result == "{}"
Beispiel #17
0
def test_ChuteApi_update_chute_tarfile(extract_tarred_chute):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    request = MagicMock()
    request.requestHeaders.getRawHeaders.return_value = ["application/x-tar"]
    request.user = User.get_internal_user()

    # Case 1: should work normally.
    workdir = "/tmp/test"
    paradrop_yaml = {
        'name': 'chute'
    }
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    data = api.update_chute(request, "chute")
    assert isinstance(data, basestring)
    result = json.loads(data)
    assert result['change_id'] == 1
    assert update_manager.add_update.called

    # Case 2: deprecated way of declaring name, but should still work.
    workdir = "/tmp/test"
    paradrop_yaml = {
        'config': {
            'name': 'chute'
        }
    }
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    data = api.update_chute(request, "chute")
    assert isinstance(data, basestring)
    result = json.loads(data)
    assert result['change_id'] == 1
    assert update_manager.add_update.called

    # Case 3: missing name, should raise exception.
    workdir = "/tmp/test"
    paradrop_yaml = {}
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    assert_raises(Exception, api.update_chute, request, "chute")
Beispiel #18
0
    def test_delete_station(self, ChuteStorage, Popen):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }

        proc = MagicMock()
        Popen.return_value = proc
        proc.stdout = [
            "OK"
        ]

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.delete_station(request, self.chute.name,
                self.interface['name'], '12:34:56:78:9a:bc')
        messages = json.loads(result)
        assert len(messages) == 1
        assert messages[0] == "OK"
    def test_set_ssid(self, ChuteStorage, execute):
        ChuteStorage.chuteList = {self.chute.name: self.chute}
        execute.return_value = "OK"

        request = MagicMock()
        request.user = User.get_internal_user()

        body = {}
        request.content.read.return_value = json.dumps(body)

        # Exception: ssid required
        assert_raises(Exception, self.api.set_ssid, request, "test", "testing")

        body = {'ssid': 'Free WiFi'}
        request.content.read.return_value = json.dumps(body)

        result = self.api.set_ssid(request, self.chute.name,
                                   self.interface['name'])
        assert result == "OK"
def test_ChuteApi_get_networks(ChuteStorage):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    iface = {'name': 'vwlan0', 'type': 'wifi', 'internalIntf': 'wlan0'}

    chute = Chute(name="test")
    chute.setCache("networkInterfaces", [iface])

    ChuteStorage.chuteList = {"test": chute}

    request = MagicMock()
    request.user = User.get_internal_user()

    result = api.get_networks(request, "test")
    data = json.loads(result)
    assert len(data) == 1
    assert data[0]['name'] == iface['name']
    assert data[0]['type'] == iface['type']
    assert data[0]['interface'] == iface['internalIntf']
Beispiel #21
0
    def test_set_ssid(self, ChuteStorage, execute):
        ChuteStorage.chuteList = {
            self.chute.name: self.chute
        }
        execute.return_value = "OK"

        request = MagicMock()
        request.user = User.get_internal_user()

        body = {}
        request.content.read.return_value = json.dumps(body)

        # Exception: ssid required
        assert_raises(Exception, self.api.set_ssid, request, "test", "testing")

        body = {
            'ssid': 'Free WiFi'
        }
        request.content.read.return_value = json.dumps(body)

        result = self.api.set_ssid(request, self.chute.name, self.interface['name'])
        assert result == "OK"
def test_ChuteApi_update_chute_tarfile(extract_tarred_chute):
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    request = MagicMock()
    request.requestHeaders.getRawHeaders.return_value = ["application/x-tar"]
    request.user = User.get_internal_user()

    # Case 1: should work normally.
    workdir = "/tmp/test"
    paradrop_yaml = {'name': 'chute'}
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    data = api.update_chute(request, "chute")
    assert isinstance(data, basestring)
    result = json.loads(data)
    assert result['change_id'] == 1
    assert update_manager.add_update.called

    # Case 2: deprecated way of declaring name, but should still work.
    workdir = "/tmp/test"
    paradrop_yaml = {'config': {'name': 'chute'}}
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    data = api.update_chute(request, "chute")
    assert isinstance(data, basestring)
    result = json.loads(data)
    assert result['change_id'] == 1
    assert update_manager.add_update.called

    # Case 3: missing name, should raise exception.
    workdir = "/tmp/test"
    paradrop_yaml = {}
    extract_tarred_chute.return_value = (workdir, paradrop_yaml)

    assert_raises(Exception, api.update_chute, request, "chute")
    def test_get_station(self, ChuteStorage, Popen):
        ChuteStorage.chuteList = {self.chute.name: self.chute}

        proc = MagicMock()
        Popen.return_value = proc
        proc.stdout = [
            "Station 12:34:56:78:9a:bc (on wlan0)", "	inactive time:  304 ms",
            "	rx bytes:       18816", "	rx packets:     75",
            "	tx bytes:       5386", "	tx packets:     21",
            "	signal:         -29 dBm", "	tx bitrate:     54.0 MBit/s"
        ]

        request = MagicMock()
        request.user = User.get_internal_user()

        result = self.api.get_station(request, self.chute.name,
                                      self.interface['name'],
                                      '12:34:56:78:9a:bc')
        station = json.loads(result)
        assert station['mac_addr'] == '12:34:56:78:9a:bc'
        assert station['rx_bytes'] == '18816'
        assert station['signal'] == '-29 dBm'
        assert station['tx_bitrate'] == '54.0 MBit/s'
def test_ChuteApi_operations():
    update_manager = MagicMock()
    update_manager.assign_change_id.return_value = 1

    api = chute_api.ChuteApi(update_manager)

    body = {'config': {}}

    request = MagicMock()
    request.content.read.return_value = json.dumps(body)
    request.user = User.get_internal_user()

    functions = [
        api.update_chute, api.stop_chute, api.start_chute, api.restart_chute,
        api.delete_chute
    ]
    for func in functions:
        print("Calling ChuteApi {}".format(func.__name__))

        data = func(request, "test")
        assert isinstance(data, basestring)

        result = json.loads(data)
        assert result['change_id'] == 1
Beispiel #25
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 = json.loads(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
Beispiel #26
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 = json.loads(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