move network controller to new world
This commit is contained in:
parent
e9071a00ca
commit
7f41803418
|
@ -3,6 +3,7 @@ subiquity/client/client.py
|
||||||
subiquity/client/controller.py
|
subiquity/client/controller.py
|
||||||
subiquity/client/controllers/__init__.py
|
subiquity/client/controllers/__init__.py
|
||||||
subiquity/client/controllers/keyboard.py
|
subiquity/client/controllers/keyboard.py
|
||||||
|
subiquity/client/controllers/network.py
|
||||||
subiquity/client/controllers/progress.py
|
subiquity/client/controllers/progress.py
|
||||||
subiquity/client/controllers/refresh.py
|
subiquity/client/controllers/refresh.py
|
||||||
subiquity/client/controllers/welcome.py
|
subiquity/client/controllers/welcome.py
|
||||||
|
@ -35,7 +36,6 @@ subiquity/controllers/filesystem.py
|
||||||
subiquity/controllers/identity.py
|
subiquity/controllers/identity.py
|
||||||
subiquity/controllers/__init__.py
|
subiquity/controllers/__init__.py
|
||||||
subiquity/controllers/mirror.py
|
subiquity/controllers/mirror.py
|
||||||
subiquity/controllers/network.py
|
|
||||||
subiquity/controllers/proxy.py
|
subiquity/controllers/proxy.py
|
||||||
subiquity/controllers/reboot.py
|
subiquity/controllers/reboot.py
|
||||||
subiquity/controllers/snaplist.py
|
subiquity/controllers/snaplist.py
|
||||||
|
@ -122,6 +122,7 @@ subiquity/server/controllers/__init__.py
|
||||||
subiquity/server/controllers/install.py
|
subiquity/server/controllers/install.py
|
||||||
subiquity/server/controllers/keyboard.py
|
subiquity/server/controllers/keyboard.py
|
||||||
subiquity/server/controllers/locale.py
|
subiquity/server/controllers/locale.py
|
||||||
|
subiquity/server/controllers/network.py
|
||||||
subiquity/server/controllers/package.py
|
subiquity/server/controllers/package.py
|
||||||
subiquity/server/controllers/refresh.py
|
subiquity/server/controllers/refresh.py
|
||||||
subiquity/server/controllers/reporting.py
|
subiquity/server/controllers/reporting.py
|
||||||
|
|
|
@ -94,6 +94,7 @@ class SubiquityClient(TuiApplication):
|
||||||
"Refresh",
|
"Refresh",
|
||||||
"Keyboard",
|
"Keyboard",
|
||||||
"Zdev",
|
"Zdev",
|
||||||
|
"Network",
|
||||||
"Progress",
|
"Progress",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .keyboard import KeyboardController
|
from .keyboard import KeyboardController
|
||||||
|
from .network import NetworkController
|
||||||
from .progress import ProgressController
|
from .progress import ProgressController
|
||||||
from .refresh import RefreshController
|
from .refresh import RefreshController
|
||||||
from .welcome import WelcomeController
|
from .welcome import WelcomeController
|
||||||
|
@ -21,6 +22,7 @@ from .zdev import ZdevController
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'KeyboardController',
|
'KeyboardController',
|
||||||
|
'NetworkController',
|
||||||
'ProgressController',
|
'ProgressController',
|
||||||
'RefreshController',
|
'RefreshController',
|
||||||
'WelcomeController',
|
'WelcomeController',
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
# Copyright 2020 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/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from subiquitycore.controllers.network import NetworkAnswersMixin
|
||||||
|
from subiquitycore.models.network import (
|
||||||
|
BondConfig,
|
||||||
|
NetDevInfo,
|
||||||
|
StaticConfig,
|
||||||
|
)
|
||||||
|
from subiquitycore.ui.views.network import NetworkView
|
||||||
|
|
||||||
|
from subiquity.client.controller import SubiquityTuiController
|
||||||
|
from subiquity.common.api.server import make_server_at_path
|
||||||
|
from subiquity.common.apidef import LinkAction, NetEventAPI
|
||||||
|
|
||||||
|
log = logging.getLogger('subiquity.client.controllers.network')
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkController(SubiquityTuiController, NetworkAnswersMixin):
|
||||||
|
|
||||||
|
endpoint_name = 'network'
|
||||||
|
|
||||||
|
def __init__(self, app):
|
||||||
|
super().__init__(app)
|
||||||
|
self.view = None
|
||||||
|
|
||||||
|
async def update_link_POST(self, act: LinkAction,
|
||||||
|
info: NetDevInfo) -> None:
|
||||||
|
if self.view is None:
|
||||||
|
return
|
||||||
|
if act == LinkAction.NEW:
|
||||||
|
self.view.new_link(info)
|
||||||
|
if act == LinkAction.CHANGE:
|
||||||
|
self.view.update_link(info)
|
||||||
|
if act == LinkAction.DEL:
|
||||||
|
self.view.del_link(info)
|
||||||
|
|
||||||
|
async def route_watch_POST(self, routes: List[int]) -> None:
|
||||||
|
if self.view is not None:
|
||||||
|
self.view.update_default_routes(routes)
|
||||||
|
|
||||||
|
async def apply_starting_POST(self) -> None:
|
||||||
|
if self.view is not None:
|
||||||
|
self.view.show_apply_spinner()
|
||||||
|
|
||||||
|
async def apply_stopping_POST(self) -> None:
|
||||||
|
if self.view is not None:
|
||||||
|
self.view.hide_apply_spinner()
|
||||||
|
|
||||||
|
async def apply_error_POST(self, stage: str) -> None:
|
||||||
|
if self.view is not None:
|
||||||
|
self.view.show_network_error(stage)
|
||||||
|
|
||||||
|
async def subscribe(self):
|
||||||
|
self.tdir = tempfile.mkdtemp()
|
||||||
|
self.sock_path = os.path.join(self.tdir, 'socket')
|
||||||
|
self.site = await make_server_at_path(
|
||||||
|
self.sock_path, NetEventAPI, self)
|
||||||
|
await self.endpoint.subscription.PUT(self.sock_path)
|
||||||
|
|
||||||
|
async def unsubscribe(self):
|
||||||
|
await self.endpoint.subscription.DELETE(self.sock_path)
|
||||||
|
await self.site.stop()
|
||||||
|
shutil.rmtree(self.tdir)
|
||||||
|
|
||||||
|
async def make_ui(self):
|
||||||
|
netdev_infos = await self.endpoint.GET()
|
||||||
|
self.view = NetworkView(self, netdev_infos)
|
||||||
|
await self.subscribe()
|
||||||
|
return self.view
|
||||||
|
|
||||||
|
def end_ui(self):
|
||||||
|
if self.view is not None:
|
||||||
|
self.view = None
|
||||||
|
self.app.aio_loop.create_task(self.unsubscribe())
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.app.prev_screen()
|
||||||
|
|
||||||
|
def done(self):
|
||||||
|
self.app.next_screen(self.endpoint.POST())
|
||||||
|
|
||||||
|
def set_static_config(self, dev_name: str, ip_version: int,
|
||||||
|
static_config: StaticConfig) -> None:
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self.endpoint.set_static_config.POST(
|
||||||
|
dev_name, ip_version, static_config))
|
||||||
|
|
||||||
|
def enable_dhcp(self, dev_name, ip_version: int) -> None:
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self.endpoint.enable_dhcp.POST(dev_name, ip_version))
|
||||||
|
|
||||||
|
def disable_network(self, dev_name: str, ip_version: int) -> None:
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self.endpoint.disable.POST(dev_name, ip_version))
|
||||||
|
|
||||||
|
def add_vlan(self, dev_name: str, vlan_id: int):
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self.endpoint.vlan.PUT(dev_name, vlan_id))
|
||||||
|
|
||||||
|
def delete_link(self, dev_name: str):
|
||||||
|
self.app.aio_loop.create_task(self.endpoint.delete.POST(dev_name))
|
||||||
|
|
||||||
|
def add_or_update_bond(self, existing_name: Optional[str],
|
||||||
|
new_name: str, new_info: BondConfig) -> None:
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self.endpoint.add_or_edit_bond.POST(
|
||||||
|
existing_name, new_name, new_info))
|
||||||
|
|
||||||
|
async def get_info_for_netdev(self, dev_name: str) -> str:
|
||||||
|
return await self.endpoint.info.GET(dev_name)
|
|
@ -13,9 +13,16 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import enum
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from subiquity.common.api.defs import api, simple_endpoint
|
from subiquitycore.models.network import (
|
||||||
|
BondConfig,
|
||||||
|
NetDevInfo,
|
||||||
|
StaticConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
from subiquity.common.api.defs import api, Payload, simple_endpoint
|
||||||
from subiquity.common.types import (
|
from subiquity.common.types import (
|
||||||
ApplicationState,
|
ApplicationState,
|
||||||
ApplicationStatus,
|
ApplicationStatus,
|
||||||
|
@ -80,6 +87,101 @@ class API:
|
||||||
class chzdev:
|
class chzdev:
|
||||||
def POST(action: str, zdev: ZdevInfo) -> List[ZdevInfo]: ...
|
def POST(action: str, zdev: ZdevInfo) -> List[ZdevInfo]: ...
|
||||||
|
|
||||||
|
class network:
|
||||||
|
def GET() -> List[NetDevInfo]: ...
|
||||||
|
def POST() -> None: ...
|
||||||
|
|
||||||
|
class global_addresses:
|
||||||
|
def GET() -> List[str]:
|
||||||
|
"""Return the global IP addresses the system currently has."""
|
||||||
|
|
||||||
|
class subscription:
|
||||||
|
"""Subscribe to networking updates.
|
||||||
|
|
||||||
|
The socket must serve the NetEventAPI below.
|
||||||
|
"""
|
||||||
|
def PUT(socket_path: str) -> None: ...
|
||||||
|
def DELETE(socket_path: str) -> None: ...
|
||||||
|
|
||||||
|
# These methods could definitely be more RESTish, like maybe a
|
||||||
|
# GET request to /network/interfaces/$name should return netplan
|
||||||
|
# config which could then be POSTed back the same path. But
|
||||||
|
# well, that's not implemented yet.
|
||||||
|
#
|
||||||
|
# (My idea is that the API definition would look something like
|
||||||
|
#
|
||||||
|
# class network:
|
||||||
|
# class interfaces:
|
||||||
|
# class dev_name:
|
||||||
|
# __subscript__ = True
|
||||||
|
# def GET() -> dict: ...
|
||||||
|
# def POST(config: Payload[dict]) -> None: ...
|
||||||
|
#
|
||||||
|
# The client would use subscripting to get a client for
|
||||||
|
# the nic, so something like
|
||||||
|
#
|
||||||
|
# dev_client = client.network[dev_name]
|
||||||
|
# config = await dev_client.GET()
|
||||||
|
# ...
|
||||||
|
# await dev_client.POST(config)
|
||||||
|
#
|
||||||
|
# The implementation would look like:
|
||||||
|
#
|
||||||
|
# class NetworkController:
|
||||||
|
#
|
||||||
|
# async def interfaces_devname_GET(dev_name: str) -> dict: ...
|
||||||
|
# async def interfaces_devname_POST(dev_name: str, config: dict) \
|
||||||
|
# -> None: ...
|
||||||
|
#
|
||||||
|
# So methods on nics get an extra dev_name: str parameter)
|
||||||
|
|
||||||
|
class set_static_config:
|
||||||
|
def POST(dev_name: str, ip_version: int,
|
||||||
|
static_config: Payload[StaticConfig]) -> None: ...
|
||||||
|
|
||||||
|
class enable_dhcp:
|
||||||
|
def POST(dev_name: str, ip_version: int) -> None: ...
|
||||||
|
|
||||||
|
class disable:
|
||||||
|
def POST(dev_name: str, ip_version: int) -> None: ...
|
||||||
|
|
||||||
|
class vlan:
|
||||||
|
def PUT(dev_name: str, vlan_id: int) -> None: ...
|
||||||
|
|
||||||
|
class add_or_edit_bond:
|
||||||
|
def POST(existing_name: Optional[str], new_name: str,
|
||||||
|
bond_config: Payload[BondConfig]) -> None: ...
|
||||||
|
|
||||||
|
class delete:
|
||||||
|
def POST(dev_name: str) -> None: ...
|
||||||
|
|
||||||
|
class info:
|
||||||
|
def GET(dev_name: str) -> str: ...
|
||||||
|
|
||||||
class install:
|
class install:
|
||||||
class status:
|
class status:
|
||||||
def GET(cur: Optional[InstallState] = None) -> InstallStatus: ...
|
def GET(cur: Optional[InstallState] = None) -> InstallStatus: ...
|
||||||
|
|
||||||
|
|
||||||
|
class LinkAction(enum.Enum):
|
||||||
|
NEW = enum.auto()
|
||||||
|
CHANGE = enum.auto()
|
||||||
|
DEL = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
|
@api
|
||||||
|
class NetEventAPI:
|
||||||
|
class update_link:
|
||||||
|
def POST(act: LinkAction, info: Payload[NetDevInfo]) -> None: ...
|
||||||
|
|
||||||
|
class route_watch:
|
||||||
|
def POST(routes: List[int]) -> None: ...
|
||||||
|
|
||||||
|
class apply_starting:
|
||||||
|
def POST() -> None: ...
|
||||||
|
|
||||||
|
class apply_stopping:
|
||||||
|
def POST() -> None: ...
|
||||||
|
|
||||||
|
class apply_error:
|
||||||
|
def POST(stage: str) -> None: ...
|
||||||
|
|
|
@ -17,7 +17,6 @@ from ..controller import RepeatedController
|
||||||
from .filesystem import FilesystemController
|
from .filesystem import FilesystemController
|
||||||
from .identity import IdentityController
|
from .identity import IdentityController
|
||||||
from .mirror import MirrorController
|
from .mirror import MirrorController
|
||||||
from .network import NetworkController
|
|
||||||
from .proxy import ProxyController
|
from .proxy import ProxyController
|
||||||
from .reboot import RebootController
|
from .reboot import RebootController
|
||||||
from .snaplist import SnapListController
|
from .snaplist import SnapListController
|
||||||
|
@ -27,7 +26,6 @@ __all__ = [
|
||||||
'FilesystemController',
|
'FilesystemController',
|
||||||
'IdentityController',
|
'IdentityController',
|
||||||
'MirrorController',
|
'MirrorController',
|
||||||
'NetworkController',
|
|
||||||
'ProxyController',
|
'ProxyController',
|
||||||
'RebootController',
|
'RebootController',
|
||||||
'RepeatedController',
|
'RepeatedController',
|
||||||
|
|
|
@ -18,6 +18,7 @@ from .debconf import DebconfController
|
||||||
from .install import InstallController
|
from .install import InstallController
|
||||||
from .keyboard import KeyboardController
|
from .keyboard import KeyboardController
|
||||||
from .locale import LocaleController
|
from .locale import LocaleController
|
||||||
|
from .network import NetworkController
|
||||||
from .package import PackageController
|
from .package import PackageController
|
||||||
from .refresh import RefreshController
|
from .refresh import RefreshController
|
||||||
from .reporting import ReportingController
|
from .reporting import ReportingController
|
||||||
|
@ -32,6 +33,7 @@ __all__ = [
|
||||||
'KeyboardController',
|
'KeyboardController',
|
||||||
'LateController',
|
'LateController',
|
||||||
'LocaleController',
|
'LocaleController',
|
||||||
|
'NetworkController',
|
||||||
'PackageController',
|
'PackageController',
|
||||||
'RefreshController',
|
'RefreshController',
|
||||||
'ReportingController',
|
'ReportingController',
|
||||||
|
|
|
@ -15,16 +15,30 @@
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
from subiquitycore.async_helpers import schedule_task
|
from subiquitycore.async_helpers import schedule_task
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.controllers.network import NetworkController
|
from subiquitycore.controllers.network import BaseNetworkController
|
||||||
|
from subiquitycore.models.network import (
|
||||||
|
BondConfig,
|
||||||
|
NetDevInfo,
|
||||||
|
StaticConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
from subiquity.common.api.client import make_client_for_conn
|
||||||
|
from subiquity.common.apidef import (
|
||||||
|
API,
|
||||||
|
LinkAction,
|
||||||
|
NetEventAPI,
|
||||||
|
)
|
||||||
from subiquity.common.errorreport import ErrorReportKind
|
from subiquity.common.errorreport import ErrorReportKind
|
||||||
from subiquity.controller import SubiquityTuiController
|
from subiquity.server.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.controllers.network")
|
log = logging.getLogger("subiquity.server.controllers.network")
|
||||||
|
|
||||||
MATCH = {
|
MATCH = {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
|
@ -65,7 +79,9 @@ NETPLAN_SCHEMA = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NetworkController(NetworkController, SubiquityTuiController):
|
class NetworkController(BaseNetworkController, SubiquityController):
|
||||||
|
|
||||||
|
endpoint = API.network
|
||||||
|
|
||||||
ai_data = None
|
ai_data = None
|
||||||
autoinstall_key = "network"
|
autoinstall_key = "network"
|
||||||
|
@ -85,6 +101,8 @@ class NetworkController(NetworkController, SubiquityTuiController):
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
app.note_file_for_apport("NetplanConfig", self.netplan_path)
|
app.note_file_for_apport("NetplanConfig", self.netplan_path)
|
||||||
|
self.view_shown = False
|
||||||
|
self.clients = {}
|
||||||
|
|
||||||
def load_autoinstall_data(self, data):
|
def load_autoinstall_data(self, data):
|
||||||
if data is not None:
|
if data is not None:
|
||||||
|
@ -171,9 +189,119 @@ class NetworkController(NetworkController, SubiquityTuiController):
|
||||||
if not self.interactive():
|
if not self.interactive():
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def done(self):
|
|
||||||
self.configured()
|
|
||||||
super().done()
|
|
||||||
|
|
||||||
def make_autoinstall(self):
|
def make_autoinstall(self):
|
||||||
return self.model.render_config()['network']
|
return self.model.render_config()['network']
|
||||||
|
|
||||||
|
async def GET(self) -> List[NetDevInfo]:
|
||||||
|
if not self.view_shown:
|
||||||
|
self.apply_config(silent=True)
|
||||||
|
self.view_shown = True
|
||||||
|
return [
|
||||||
|
netdev.netdev_info() for netdev in self.model.get_all_netdevs()
|
||||||
|
]
|
||||||
|
|
||||||
|
def configured(self):
|
||||||
|
self.model.has_network = bool(
|
||||||
|
self.network_event_receiver.default_routes)
|
||||||
|
super().configured()
|
||||||
|
|
||||||
|
async def POST(self) -> None:
|
||||||
|
self.configured()
|
||||||
|
|
||||||
|
async def global_addresses_GET(self) -> List[str]:
|
||||||
|
ips = []
|
||||||
|
for dev in self.model.get_all_netdevs():
|
||||||
|
ips.extend(map(str, dev.actual_global_ip_addresses))
|
||||||
|
return ips
|
||||||
|
|
||||||
|
async def subscription_PUT(self, socket_path: str) -> None:
|
||||||
|
log.debug('added subscription %s', socket_path)
|
||||||
|
conn = aiohttp.UnixConnector(socket_path)
|
||||||
|
client = make_client_for_conn(NetEventAPI, conn)
|
||||||
|
lock = asyncio.Lock()
|
||||||
|
self.clients[socket_path] = (client, conn, lock)
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self._call_client(
|
||||||
|
client, conn, lock, "route_watch",
|
||||||
|
self.network_event_receiver.default_routes))
|
||||||
|
|
||||||
|
async def subscription_DELETE(self, socket_path: str) -> None:
|
||||||
|
if socket_path not in self.clients:
|
||||||
|
return
|
||||||
|
log.debug('removed subscription %s', socket_path)
|
||||||
|
client, conn, lock = self.clients.pop(socket_path)
|
||||||
|
async with lock:
|
||||||
|
await conn.close()
|
||||||
|
|
||||||
|
async def _call_client(self, client, conn, lock, meth_name, *args):
|
||||||
|
async with lock:
|
||||||
|
log.debug("_call_client %s %s", meth_name, conn.path)
|
||||||
|
if conn.closed:
|
||||||
|
log.debug('closed')
|
||||||
|
return
|
||||||
|
await getattr(client, meth_name).POST(*args)
|
||||||
|
|
||||||
|
def _call_clients(self, meth_name, *args):
|
||||||
|
for client, conn, lock in self.clients.values():
|
||||||
|
log.debug('creating _call_client task %s %s', conn.path, meth_name)
|
||||||
|
self.app.aio_loop.create_task(
|
||||||
|
self._call_client(client, conn, lock, meth_name, *args))
|
||||||
|
|
||||||
|
def apply_starting(self):
|
||||||
|
super().apply_starting()
|
||||||
|
self._call_clients("apply_starting")
|
||||||
|
|
||||||
|
def apply_stopping(self):
|
||||||
|
super().apply_stopping()
|
||||||
|
self._call_clients("apply_stopping")
|
||||||
|
|
||||||
|
def apply_error(self, stage):
|
||||||
|
super().apply_error()
|
||||||
|
self._call_clients("apply_error", stage)
|
||||||
|
|
||||||
|
def update_default_routes(self, routes):
|
||||||
|
super().update_default_routes(routes)
|
||||||
|
self._call_clients("route_watch", routes)
|
||||||
|
|
||||||
|
def _send_update(self, act, dev):
|
||||||
|
with self.context.child(
|
||||||
|
"_send_update", "{} {}".format(act.name, dev.name)):
|
||||||
|
log.debug("dev_info {} {}".format(dev.name, dev.config))
|
||||||
|
dev_info = dev.netdev_info()
|
||||||
|
self._call_clients("update_link", act, dev_info)
|
||||||
|
|
||||||
|
def new_link(self, dev):
|
||||||
|
super().new_link(dev)
|
||||||
|
self._send_update(LinkAction.NEW, dev)
|
||||||
|
|
||||||
|
def update_link(self, dev):
|
||||||
|
super().update_link(dev)
|
||||||
|
self._send_update(LinkAction.CHANGE, dev)
|
||||||
|
|
||||||
|
def del_link(self, dev):
|
||||||
|
super().del_link(dev)
|
||||||
|
self._send_update(LinkAction.DEL, dev)
|
||||||
|
|
||||||
|
async def set_static_config_POST(self, dev_name: str, ip_version: int,
|
||||||
|
static_config: StaticConfig) -> None:
|
||||||
|
self.set_static_config(dev_name, ip_version, static_config)
|
||||||
|
|
||||||
|
async def enable_dhcp_POST(self, dev_name: str, ip_version: int) -> None:
|
||||||
|
self.enable_dhcp(dev_name, ip_version)
|
||||||
|
|
||||||
|
async def disable_POST(self, dev_name: str, ip_version: int) -> None:
|
||||||
|
self.disable_network(dev_name, ip_version)
|
||||||
|
|
||||||
|
async def vlan_PUT(self, dev_name: str, vlan_id: int) -> None:
|
||||||
|
self.add_vlan(dev_name, vlan_id)
|
||||||
|
|
||||||
|
async def add_or_edit_bond_POST(self, existing_name: Optional[str],
|
||||||
|
new_name: str,
|
||||||
|
bond_config: BondConfig) -> None:
|
||||||
|
self.add_or_update_bond(existing_name, new_name, bond_config)
|
||||||
|
|
||||||
|
async def delete_POST(self, dev_name: str) -> None:
|
||||||
|
self.delete_link(dev_name)
|
||||||
|
|
||||||
|
async def info_GET(self, dev_name: str) -> str:
|
||||||
|
return await self.get_info_for_netdev(dev_name)
|
|
@ -122,6 +122,7 @@ class SubiquityServer(Application):
|
||||||
"Refresh",
|
"Refresh",
|
||||||
"Keyboard",
|
"Keyboard",
|
||||||
"Zdev",
|
"Zdev",
|
||||||
|
"Network",
|
||||||
"Install",
|
"Install",
|
||||||
"Late",
|
"Late",
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue