<commit_before># Copyright 2015 Canonical, Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from functools import partial
import logging
import os
import subprocess

import yaml

from probert.network import IFF_UP, NetworkEventReceiver

from subiquitycore.models.network import BondParameters, sanitize_config
from subiquitycore.tasksequence import (
    BackgroundTask,
    BackgroundProcess,
    PythonSleep,
    TaskSequence,
    TaskWatcher,
    )
from subiquitycore.ui.views.network import (
    NetworkView,
    )
from subiquitycore.controller import BaseController
from subiquitycore.utils import run_command
from subiquitycore.file_util import write_file
from subiquitycore import netplan

log = logging.getLogger("subiquitycore.controller.network")


class DownNetworkDevices(BackgroundTask):

    def __init__(self, rtlistener, devs_to_down, devs_to_delete):
        self.rtlistener = rtlistener
        self.devs_to_down = devs_to_down
        self.devs_to_delete = devs_to_delete

    def __repr__(self):
        return 'DownNetworkDevices({}, {})'.format(
            [dev.name for dev in self.devs_to_down],
            [dev.name for dev in self.devs_to_delete],
            )

    def start(self):
        pass

    def _bg_run(self):
        for dev in self.devs_to_down:
            try:
                log.debug('downing %s', dev.name)
                self.rtlistener.unset_link_flags(dev.ifindex, IFF_UP)
            except RuntimeError:
                # We don't actually care very much about this
                log.exception('unset_link_flags failed for %s', dev.name)
        for dev in self.devs_to_delete:
            # XXX would be nicer to do this via rtlistener eventually.
            log.debug('deleting %s', dev.name)
            cmd = ['ip', 'link', 'delete', 'dev', dev.name]
            try:
                run_command(cmd, check=True)
            except subprocess.CalledProcessError as cp:
                log.info("deleting %s failed with %r", dev.name, cp.stderr)

    def end(self, observer, fut):
        observer.task_succeeded()


class ApplyWatcher(TaskWatcher):
    def __init__(self, view, controller):
        self.view = view
        self.controller = controller

    def task_complete(self, stage):
        pass

    def tasks_finished(self):
        self.view.hide_apply_spinner()
        if self.controller.answers.get('accept-default', False):
            self.controller.done()
        elif self.controller.answers.get('actions', False):
            self.controller._run_iterator(
                self.controller._run_actions(
                    self.controller.answers['actions']))

    def task_error(self, stage, info):
        self.view.show_network_error(stage, info)


class SubiquityNetworkEventReceiver(NetworkEventReceiver):
    def __init__(self, model):
        self.model = model
        self.view = None
        self.default_route_watchers = []
        self.default_routes = set()

    def new_link(self, ifindex, link):
        netdev = self.model.new_link(ifindex, link)
        if self.view is not None and netdev is not None:
            self.view.new_link(netdev)

    def del_link(self, ifindex):
        netdev = self.model.del_link(ifindex)
        if ifindex in self.default_routes:
            self.default_routes.remove(ifindex)
        if self.view is not None and netdev is not None:
            self.view.del_link(netdev)

    def update_link(self, ifindex):
        netdev = self.model.update_link(ifindex)
        if self.view is not None and netdev is not None:
            self.view.update_link(netdev)

    def route_change(self, action, data):
        super().route_change(action, data)
        if data['dst'] != 'default':
            return
        if data['table'] != 254:
            return
        ifindex = data['ifindex']
        if action == "NEW" or action == "CHANGE":
            self.default_routes.add(ifindex)
        elif action == "DEL" and ifindex in self.default_routes:
            self.default_routes.remove(ifindex)
        for watcher in self.default_route_watchers:
            watcher(self.default_routes)
        log.debug('default routes %s', self.default_routes)

    def add_default_route_watcher(self, watcher):
        self.default_route_watchers.append(watcher)
        watcher(self.default_routes)

    def remove_default_route_watcher(self, watcher):<commit_msg>assume a default route on a down link has gone away<commit_after># Copyright 2015 Canonical, Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from functools import partial
import logging
import os
import subprocess

import yaml

from probert.network import IFF_UP, NetworkEventReceiver

from subiquitycore.models.network import BondParameters, sanitize_config
from subiquitycore.tasksequence import (
    BackgroundTask,
    BackgroundProcess,
    PythonSleep,
    TaskSequence,
    TaskWatcher,
    )
from subiquitycore.ui.views.network import (
    NetworkView,
    )
from subiquitycore.controller import BaseController
from subiquitycore.utils import run_command
from subiquitycore.file_util import write_file
from subiquitycore import netplan

log = logging.getLogger("subiquitycore.controller.network")


class DownNetworkDevices(BackgroundTask):

    def __init__(self, rtlistener, devs_to_down, devs_to_delete):
        self.rtlistener = rtlistener
        self.devs_to_down = devs_to_down
        self.devs_to_delete = devs_to_delete

    def __repr__(self):
        return 'DownNetworkDevices({}, {})'.format(
            [dev.name for dev in self.devs_to_down],
            [dev.name for dev in self.devs_to_delete],
            )

    def start(self):
        pass

    def _bg_run(self):
        for dev in self.devs_to_down:
            try:
                log.debug('downing %s', dev.name)
                self.rtlistener.unset_link_flags(dev.ifindex, IFF_UP)
            except RuntimeError:
                # We don't actually care very much about this
                log.exception('unset_link_flags failed for %s', dev.name)
        for dev in self.devs_to_delete:
            # XXX would be nicer to do this via rtlistener eventually.
            log.debug('deleting %s', dev.name)
            cmd = ['ip', 'link', 'delete', 'dev', dev.name]
            try:
                run_command(cmd, check=True)
            except subprocess.CalledProcessError as cp:
                log.info("deleting %s failed with %r", dev.name, cp.stderr)

    def end(self, observer, fut):
        observer.task_succeeded()


class ApplyWatcher(TaskWatcher):
    def __init__(self, view, controller):
        self.view = view
        self.controller = controller

    def task_complete(self, stage):
        pass

    def tasks_finished(self):
        self.view.hide_apply_spinner()
        if self.controller.answers.get('accept-default', False):
            self.controller.done()
        elif self.controller.answers.get('actions', False):
            self.controller._run_iterator(
                self.controller._run_actions(
                    self.controller.answers['actions']))

    def task_error(self, stage, info):
        self.view.show_network_error(stage, info)


class SubiquityNetworkEventReceiver(NetworkEventReceiver):
    def __init__(self, model):
        self.model = model
        self.view = None
        self.default_route_watchers = []
        self.default_routes = set()

    def new_link(self, ifindex, link):
        netdev = self.model.new_link(ifindex, link)
        if self.view is not None and netdev is not None:
            self.view.new_link(netdev)

    def del_link(self, ifindex):
        netdev = self.model.del_link(ifindex)
        if ifindex in self.default_routes:
            self.default_routes.remove(ifindex)
        if self.view is not None and netdev is not None:
            self.view.del_link(netdev)

    def update_link(self, ifindex):
        netdev = self.model.update_link(ifindex)
        if netdev is None:
            return
        if not (netdev.info.flags & IFF_UP) and ifindex in self.default_routes:
            self.default_routes.remove(ifindex)
            for watcher in self.default_route_watchers:
                watcher(self.default_routes)
        if self.view is not None:
            self.view.update_link(netdev)

    def route_change(self, action, data):
        super().route_change(action, data)
        if data['dst'] != 'default':
            return
        if data['table'] != 254:
            return
        ifindex = data['ifindex']
        if action == "NEW" or action == "CHANGE":
            self.default_routes.add(ifindex)
        elif action == "DEL" and ifindex in self.default_routes:
            self.default_routes.remove(ifindex)
        for watcher in self.default_route_watchers:
            watcher(self.default_routes)
        log.debug('default routes %s', self.default_routes)

    def add_default_route_watcher(self, watcher):
        self.default_route_watchers.append(watcher)
        watcher(self.default_routes)

    def remove_default_route_watcher(self, watcher):
{'fraction_non_alphanumeric': 0.08427293934681182, 'fraction_numerical': 0.0015552099533437014, 'mean_word_length': 2.673330953230989, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '508069', 'n_tokens_mistral': 2983, 'n_tokens_neox': 2909, 'n_words': 837}