Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(monitoring): show wan public ip address #438

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 67 additions & 17 deletions src/components/standalone/monitoring/ConnectivityMonitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ import {
NeInlineNotification,
sortByProperty
} from '@nethesis/vue-components'
import { computed, onMounted, ref } from 'vue'
import { computed, onMounted, ref, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import WanEventsCard from './connectivity/WanEventsCard.vue'
import { isEmpty } from 'lodash-es'
import type { Policy } from '@/composables/useMwan'
import WanConnectionsCard from './connectivity/WanConnectionsCard.vue'
import { useNetworkDevices } from '@/composables/useNetworkDevices'
import { getIpv4Addresses, getIpv6Addresses, getName, isDeviceUp } from '@/lib/standalone/network'
import {
getIpv4Addresses,
getIpv6Addresses,
getName,
isDeviceUp,
isIpv6Enabled,
type DeviceOrIface
} from '@/lib/standalone/network'
import { useUciNetworkConfig } from '@/composables/useUciNetworkConfig'
import InterfaceTrafficCard from './connectivity/InterfaceTrafficCard.vue'
import { useLatencyAndQualityReport } from '@/composables/useLatencyAndQualityReport'
Expand All @@ -32,8 +39,7 @@ export type Wan = {
iface: string
device: string
status?: string
ip4Addresses?: string[]
ip6Addresses?: string[]
ipAddresses?: string[]
}

export type WanEvent = {
Expand All @@ -56,6 +62,7 @@ const router = useRouter()
const wans = ref<Wan[]>([])
const mwanEvents = ref<Record<string, any[]>>({})
const mwanPolicies = ref<Policy[]>([])
const wanConnections = ref<Wan[]>([])

const {
latencyAndQualityCharts,
Expand All @@ -76,7 +83,9 @@ let error = ref({
getMwanReport: '',
getMwanReportDetails: '',
getMwanPolicies: '',
getMwanPoliciesDetails: ''
getMwanPoliciesDetails: '',
getPublicIpAddresses: '',
getPublicIpAddressesDetails: ''
})

const loadingData = computed(() => {
Expand All @@ -89,7 +98,7 @@ const loadingData = computed(() => {
)
})

const wanConnections = computed(() => {
watchEffect(async () => {
const wanData: Wan[] = []

for (const wan of wans.value) {
Expand All @@ -112,14 +121,17 @@ const wanConnections = computed(() => {
if (policyMember.interface == wan.iface) {
const devFound = allDevices.value.find((dev) => getName(dev) === wan.device)

wanData.push({
...wan,
status: policyMember.status,
ip4Addresses: devFound ? getIpv4Addresses(devFound, networkConfig.value) : [],
ip6Addresses: devFound ? getIpv6Addresses(devFound, networkConfig.value) : []
})
statusFound = true
break
if (devFound) {
const publicIpAddresses = await retrievePublicIpAddresses(devFound)

wanData.push({
...wan,
status: policyMember.status,
ipAddresses: publicIpAddresses
})
statusFound = true
break
}
}
}
}
Expand All @@ -130,16 +142,17 @@ const wanConnections = computed(() => {
const devFound = allDevices.value.find((dev) => getName(dev) === wan.device)

if (devFound) {
const publicIpAddresses = await retrievePublicIpAddresses(devFound)

wanData.push({
...wan,
status: isDeviceUp(devFound, allDevices.value) ? 'online' : 'offline',
ip4Addresses: getIpv4Addresses(devFound, networkConfig.value),
ip6Addresses: getIpv6Addresses(devFound, networkConfig.value)
ipAddresses: publicIpAddresses
})
}
}
}
return wanData.sort(sortByProperty('iface'))
wanConnections.value = wanData.sort(sortByProperty('iface'))
})

onMounted(() => {
Expand All @@ -150,6 +163,27 @@ onMounted(() => {
getNetworkConfig()
})

async function retrievePublicIpAddresses(device: DeviceOrIface) {
let ipAddresses = []
let publicIpAddresses: string[] = []

if (isIpv6Enabled(device)) {
ipAddresses = getIpv6Addresses(device, networkConfig.value).concat(
getIpv4Addresses(device, networkConfig.value)
)
} else {
ipAddresses = getIpv4Addresses(device, networkConfig.value)
}
const ipAddr = ipAddresses[0].split('/')[0]
publicIpAddresses = await getPublicIpAddresses(ipAddr)

if (publicIpAddresses.length == 0 || publicIpAddresses[0] == '') {
// cannot retrieve public IP address, using interface IP address as fallback
publicIpAddresses = ipAddresses
}
return publicIpAddresses
}

async function listWans() {
loading.value.listWans = true
error.value.listWans = ''
Expand Down Expand Up @@ -197,6 +231,22 @@ async function getMwanReport() {
}
}

async function getPublicIpAddresses(privateIpAddr: string) {
error.value.getPublicIpAddresses = ''
error.value.getPublicIpAddressesDetails = ''

try {
const res = await ubusCall('ns.report', 'get-public-ip-addresses', {
ip_address: privateIpAddr
})
return res.data.public_ip_addresses
} catch (err: any) {
console.error(err)
error.value.getPublicIpAddresses = t(getAxiosErrorMessage(err))
error.value.getPublicIpAddressesDetails = err.toString()
}
}

async function getMwanPolicies() {
loading.value.getMwanPolicies = true
error.value.getMwanPolicies = ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function getQosRule(item: Wan) {
<NeTableHeadCell>{{ t('standalone.real_time_monitor.interface') }}</NeTableHeadCell>
<NeTableHeadCell>{{ t('standalone.real_time_monitor.device') }}</NeTableHeadCell>
<NeTableHeadCell>{{ t('common.status') }}</NeTableHeadCell>
<NeTableHeadCell>{{ t('common.ip_address') }}</NeTableHeadCell>
<NeTableHeadCell>{{ t('standalone.real_time_monitor.public_ip_address') }}</NeTableHeadCell>
<NeTableHeadCell>{{ t('standalone.qos.title_short') }}</NeTableHeadCell>
</NeTableHead>
<NeTableBody>
Expand Down Expand Up @@ -120,9 +120,9 @@ function getQosRule(item: Wan) {
}}
</div>
</NeTableCell>
<NeTableCell :data-label="t('common.ip_address')">
<span v-if="item.ip4Addresses.length || item.ip6Addresses.length">
{{ (item.ip4Addresses || []).concat(item.ip6Addresses || []).join(', ') }}
<NeTableCell :data-label="t('standalone.real_time_monitor.public_ip_address')">
<span v-if="item.ipAddresses.length">
{{ item.ipAddresses.join(', ') }}
</span>
<span v-else>-</span>
</NeTableCell>
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1962,7 +1962,8 @@
"ping_host_latency": "Latency to {pingHost}",
"ping_host_packet_delivery_rate": "Packet delivery rate to {pingHost}",
"latency_and_packet_delivery_rate": "Latency and packet delivery rate",
"no_hosts_configured_for_monitoring": "No hosts configured for monitoring"
"no_hosts_configured_for_monitoring": "No hosts configured for monitoring",
"public_ip_address": "Public IP address"
},
"ping_latency_monitor": {
"title": "Ping latency monitor",
Expand Down
5 changes: 5 additions & 0 deletions src/lib/standalone/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,8 @@ export function getVlanParent(bridgeDevice: DeviceOrIface, allDevices: DeviceOrI
const deviceFound = allDevices.find((dev) => dev.name === parentDevice)
return deviceFound
}

export function isIpv6Enabled(device: DeviceOrIface) {
const iface = getInterface(device)
return device.ipv6 === '1' || (iface.proto === 'pppoe' && device.ipv6 === 'auto')
}