Loading www/modules/network.js +35 −3 Changes for www/modules/network.js: 35 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -112,17 +112,32 @@ 'Check the endpoint: the peer must reach this host under that name, and the port must be open.': 'Den Endpunkt prüfen: der Peer muss diesen Host unter dem Namen erreichen, und der Port muss offen sein.', '{0}, its configuration and its peers are removed.': '{0}, seine Konfiguration und seine Peers werden entfernt.', 'Container networks (veth)': 'Container-Netzwerke (veth)', 'Container': 'Container', 'Bridge': 'Bridge', 'unknown container': 'unbekannter Container', 'The host\'s ends of the containers\' veth pairs; containerd makes and removes them with the containers (Containers page).': 'Die Host-Enden der veth-Paare der Container; containerd legt sie mit den Containern an und entfernt sie (Seite Container).', }}); let root; let interfaces = []; let netdevs = []; let vethOwners = {}; // veth -> container (containerd), if containerd is there // the host end of a veth pair (syslite says so; older ones only by name) const isVeth = i => i.kind === 'veth' || (!i.kind && i.name.startsWith('veth')); async function load() { const r = await run(() => call('network', 'list')); if (!r) return; interfaces = r.interfaces || []; netdevs = r.netdevs || []; vethOwners = {}; if (interfaces.some(isVeth)) { try { const c = await call('containers', 'list'); for (const x of c.containers || []) if (x.veth) vethOwners[x.veth] = x.name; } catch (e) { /* no containers module or no containerd: just no names */ } } draw(); } Loading @@ -139,7 +154,7 @@ function candidates(nd, kind) { const name = nd ? nd.name : null; const nesting = i => kind === 'bridge' && i.kind === 'bond' && netdevs.some(n => n.name === i.name && n.kind === 'bond'); return interfaces.filter(i => i.name !== 'lo' && i.name !== name && return interfaces.filter(i => i.name !== 'lo' && i.name !== name && !isVeth(i) && ((!i.kind && !netdevs.some(n => n.name === i.name)) || nesting(i)) && !netdevs.some(n => n.name !== name && n.members.includes(i.name))); } Loading Loading @@ -709,9 +724,26 @@ ownConfig(i) && !i.memberOf && !i.kind ? h('button', {class: 'small danger', onclick: () => deleteConfig(i)}, t('Delete config')) : null, orphan(i) ? h('button', {class: 'small danger', onclick: () => deleteOrphan(i)}, t('Delete')) : null, ]}, ], interfaces, t('No interfaces found.'))), ], interfaces.filter(i => !isVeth(i)), t('No interfaces found.'))), netdevPanel(), wireguardPanel()); wireguardPanel(), vethPanel()); } // the containers' veths: their own panel at the bottom, only when there are some function vethPanel() { const veths = interfaces.filter(isVeth); if (!veths.length) return ''; return h('section', {class: 'panel'}, h('div', {class: 'toolbar'}, h('h2', {}, t('Container networks (veth)'))), table([ {title: t('Interface'), render: i => h('strong', {}, i.name)}, {title: t('Container'), render: i => vethOwners[i.name] || h('span', {class: 'muted'}, t('unknown container'))}, {title: t('Bridge'), render: i => i.master || h('span', {class: 'muted'}, '–')}, {title: t('MAC'), render: i => i.mac, class: 'mono'}, {title: t('Status'), render: state}, ], veths), h('p', {class: 'hint'}, t('The host\'s ends of the containers\' veth pairs; containerd makes and removes them with the containers (Containers page).'))); } webctl.register('network', { Loading Loading
www/modules/network.js +35 −3 Changes for www/modules/network.js: 35 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -112,17 +112,32 @@ 'Check the endpoint: the peer must reach this host under that name, and the port must be open.': 'Den Endpunkt prüfen: der Peer muss diesen Host unter dem Namen erreichen, und der Port muss offen sein.', '{0}, its configuration and its peers are removed.': '{0}, seine Konfiguration und seine Peers werden entfernt.', 'Container networks (veth)': 'Container-Netzwerke (veth)', 'Container': 'Container', 'Bridge': 'Bridge', 'unknown container': 'unbekannter Container', 'The host\'s ends of the containers\' veth pairs; containerd makes and removes them with the containers (Containers page).': 'Die Host-Enden der veth-Paare der Container; containerd legt sie mit den Containern an und entfernt sie (Seite Container).', }}); let root; let interfaces = []; let netdevs = []; let vethOwners = {}; // veth -> container (containerd), if containerd is there // the host end of a veth pair (syslite says so; older ones only by name) const isVeth = i => i.kind === 'veth' || (!i.kind && i.name.startsWith('veth')); async function load() { const r = await run(() => call('network', 'list')); if (!r) return; interfaces = r.interfaces || []; netdevs = r.netdevs || []; vethOwners = {}; if (interfaces.some(isVeth)) { try { const c = await call('containers', 'list'); for (const x of c.containers || []) if (x.veth) vethOwners[x.veth] = x.name; } catch (e) { /* no containers module or no containerd: just no names */ } } draw(); } Loading @@ -139,7 +154,7 @@ function candidates(nd, kind) { const name = nd ? nd.name : null; const nesting = i => kind === 'bridge' && i.kind === 'bond' && netdevs.some(n => n.name === i.name && n.kind === 'bond'); return interfaces.filter(i => i.name !== 'lo' && i.name !== name && return interfaces.filter(i => i.name !== 'lo' && i.name !== name && !isVeth(i) && ((!i.kind && !netdevs.some(n => n.name === i.name)) || nesting(i)) && !netdevs.some(n => n.name !== name && n.members.includes(i.name))); } Loading Loading @@ -709,9 +724,26 @@ ownConfig(i) && !i.memberOf && !i.kind ? h('button', {class: 'small danger', onclick: () => deleteConfig(i)}, t('Delete config')) : null, orphan(i) ? h('button', {class: 'small danger', onclick: () => deleteOrphan(i)}, t('Delete')) : null, ]}, ], interfaces, t('No interfaces found.'))), ], interfaces.filter(i => !isVeth(i)), t('No interfaces found.'))), netdevPanel(), wireguardPanel()); wireguardPanel(), vethPanel()); } // the containers' veths: their own panel at the bottom, only when there are some function vethPanel() { const veths = interfaces.filter(isVeth); if (!veths.length) return ''; return h('section', {class: 'panel'}, h('div', {class: 'toolbar'}, h('h2', {}, t('Container networks (veth)'))), table([ {title: t('Interface'), render: i => h('strong', {}, i.name)}, {title: t('Container'), render: i => vethOwners[i.name] || h('span', {class: 'muted'}, t('unknown container'))}, {title: t('Bridge'), render: i => i.master || h('span', {class: 'muted'}, '–')}, {title: t('MAC'), render: i => i.mac, class: 'mono'}, {title: t('Status'), render: state}, ], veths), h('p', {class: 'hint'}, t('The host\'s ends of the containers\' veth pairs; containerd makes and removes them with the containers (Containers page).'))); } webctl.register('network', { Loading