From 9739f241beb20fa2c94435d660b60feb8e86b461 Mon Sep 17 00:00:00 2001 From: fluepke Date: Fri, 4 Dec 2020 20:07:04 +0100 Subject: [PATCH] Add scraping of station status --- collector/api.go | 100 ++++++++++++++++++-------------- collector/collector.go | 129 +++++++++++++++++++++++++++++++++++++++++ main.go | 6 ++ 3 files changed, 193 insertions(+), 42 deletions(-) diff --git a/collector/api.go b/collector/api.go index 770e877..add3127 100644 --- a/collector/api.go +++ b/collector/api.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/prometheus/common/log" "golang.org/x/crypto/pbkdf2" "io/ioutil" "net/http" @@ -102,47 +103,47 @@ type StationStatusReponse struct { } type StationStatusData struct { - DateAndTime string `json:"dateandtime"` - FirewallStatus string `json:"firewallstatus"` - LanIpv4 string `json:"lanipv4"` - LanMode string `json:"LanMode"` - LanGateway string `json:"langateway"` - LanDHCPstatus string `json:"lanDHCPstatus"` - LanMAC string `json:"lanMAC"` - LanPortStatus4 string `json:"lanportstatus_4"` - LanPortSpeed4 string `json:"lanportspeed_4"` - LanPortStatus1 string `json:"lanportstatus_1"` - LanPortSpeed1 string `json:"lanportspeed_1"` - LanPortStatus2 string `json:"lanportstatus_2"` - LanPortSpeed2 string `json:"lanportspeed_2"` - LanPortStatus3 string `json:"lanportstatus_3"` - LanPortSpeed3 string `json:"lanportspeed_3"` - WifiStatus string `json:"wifistatus"` - Channel string `json:"channel"` - Bandwidth string `json:"bandwidth"` - MaxSpeed string `json:"maxspeed"` - Ssid string `json:"ssid"` - MacAddress string `json:"macaddress"` - Security string `json:"security"` - WifiStatus5 string `json:"wifistatus_5"` - Channel5 string `json:"channel_5"` - Bandwidth5 string `json:"bandwidth_5"` - MaxSpeed5 string `json:"maxspeed_5"` - Ssid5 string `json:"ssid_5"` - Macaddress5 string `json:"macaddress_5"` - Security5 string `json:"security_5"` - DnsEntries string `json:"DnsEntries"` - AFTR string `json:"AFTR"` - Serialnumber string `json:"serialnumber"` - FirmwareVersion string `json:"firmwareversion"` - HardwareType string `json:"hardwaretype"` - Uptime string `json:"uptime"` - InternetIpv4 string `json:"internetipv4"` - DnsTbl string `json:"Dns_Tbl"` - DelegatedPrefix string `json:"DelegatedPrefix"` - DNSTblRT string `json:"DNSTblRT"` - IPAddressRT string `json:"IPAddressRT"` - IpPrefixClass string `json:"IpPrefixClass"` + DateAndTime string `json:"dateandtime"` + FirewallStatus string `json:"firewallstatus"` + LanIpv4 string `json:"lanipv4"` + LanMode string `json:"LanMode"` + LanGateway string `json:"langateway"` + LanDHCPstatus string `json:"lanDHCPstatus"` + LanMAC string `json:"lanMAC"` + LanPortStatus4 string `json:"lanportstatus_4"` + LanPortSpeed4 string `json:"lanportspeed_4"` + LanPortStatus1 string `json:"lanportstatus_1"` + LanPortSpeed1 string `json:"lanportspeed_1"` + LanPortStatus2 string `json:"lanportstatus_2"` + LanPortSpeed2 string `json:"lanportspeed_2"` + LanPortStatus3 string `json:"lanportstatus_3"` + LanPortSpeed3 string `json:"lanportspeed_3"` + WifiStatus string `json:"wifistatus"` + Channel string `json:"channel"` + Bandwidth string `json:"bandwidth"` + MaxSpeed string `json:"maxspeed"` + Ssid string `json:"ssid"` + MacAddress string `json:"macaddress"` + Security string `json:"security"` + WifiStatus5 string `json:"wifistatus_5"` + Channel5 string `json:"channel_5"` + Bandwidth5 string `json:"bandwidth_5"` + MaxSpeed5 string `json:"maxspeed_5"` + Ssid5 string `json:"ssid_5"` + MacAddress5 string `json:"macaddress_5"` + Security5 string `json:"security_5"` + DnsEntries string `json:"DnsEntries"` + AFTR string `json:"AFTR"` + Serialnumber string `json:"serialnumber"` + FirmwareVersion string `json:"firmwareversion"` + HardwareType string `json:"hardwaretype"` + Uptime string `json:"uptime"` + InternetIpv4 string `json:"internetipv4"` + DnsTbl []string `json:"Dns_Tbl"` + DelegatedPrefix string `json:"DelegatedPrefix"` + DNSTblRT []string `json:"DNSTblRT"` + IPAddressRT []string `json:"IPAddressRT"` + IpPrefixClass string `json:"IpPrefixClass"` } func NewVodafoneStation(stationUrl, password string) *VodafoneStation { @@ -162,7 +163,7 @@ func NewVodafoneStation(stationUrl, password string) *VodafoneStation { Password: password, client: &http.Client{ Jar: cookieJar, - Timeout: time.Second * 10, + Timeout: time.Second * 20, // getting DOCSIS status can be slow! }, } } @@ -215,6 +216,9 @@ func (v *VodafoneStation) GetDocsisStatus() (*DocsisStatusResponse, error) { } func (v *VodafoneStation) GetStationStatus() (*StationStatusReponse, error) { + if err := v.CheckTimeout(); err != nil { + return nil, err + } responseBody, err := v.doRequest("GET", v.URL+"/api/v1/sta_status?_="+strconv.FormatInt(makeTimestamp(), 10), "") if err != nil { return nil, err @@ -223,6 +227,14 @@ func (v *VodafoneStation) GetStationStatus() (*StationStatusReponse, error) { return stationStatusReponse, json.Unmarshal(responseBody, stationStatusReponse) } +func (v *VodafoneStation) CheckTimeout() error { + _, err := v.doRequest("GET", v.URL+"/api/v1/CheckTimeOut?_="+strconv.FormatInt(makeTimestamp(), 10), "") + if err != nil { + return err + } + return nil +} + func makeTimestamp() int64 { return time.Now().UnixNano() / int64(time.Millisecond) } @@ -244,9 +256,12 @@ func (v *VodafoneStation) getLoginSalts() (*LoginResponseSalts, error) { } func (v *VodafoneStation) doRequest(method, url, body string) ([]byte, error) { + logger := log.With("method", method).With("url", url) + logger.Debug("Performing request") requestBody := strings.NewReader(body) request, err := http.NewRequest(method, url, requestBody) if err != nil { + logger.With("error", err.Error).Error("Creating request failed") return nil, err } if method == "POST" { @@ -256,6 +271,7 @@ func (v *VodafoneStation) doRequest(method, url, body string) ([]byte, error) { request.Header.Set("X-Requested-With", "XMLHttpRequest") response, err := v.client.Do(request) if err != nil { + logger.With("error", err.Error).Error("Performing request failed") return nil, err } if response.Body != nil { diff --git a/collector/collector.go b/collector/collector.go index a18bd74..e7f488e 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -1,7 +1,9 @@ package collector import ( + "fmt" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" "regexp" "strconv" ) @@ -34,6 +36,32 @@ var ( powerUpstreamDesc *prometheus.Desc rangingStatusUpstreamDesc *prometheus.Desc + firewallStatusDesc *prometheus.Desc + lanIPv4Desc *prometheus.Desc + lanModeDesc *prometheus.Desc + lanGatewayDesc *prometheus.Desc + lanDhcpEnabledDesc *prometheus.Desc + lanMacDesc *prometheus.Desc + lanPortStatusDesc *prometheus.Desc + lanPortSpeedDesc *prometheus.Desc + wlanEnabledDesc *prometheus.Desc + wlanChannelDesc *prometheus.Desc + wlanBandwidthDesc *prometheus.Desc + wlanMaxSpeedDesc *prometheus.Desc + wlanSsidDesc *prometheus.Desc + wlanMacAddressDesc *prometheus.Desc + wlanSecurityDesc *prometheus.Desc + dnsEntriesCountDesc *prometheus.Desc + aftrDesc *prometheus.Desc + seralnumberDesc *prometheus.Desc + firmwareVersionDesc *prometheus.Desc + hardwareTypeDesc *prometheus.Desc + uptimeDesc *prometheus.Desc + internetIPv4Desc *prometheus.Desc + delegatedPrefixDesc *prometheus.Desc + ipAddressRTDesc *prometheus.Desc + ipPrefixClassDesc *prometheus.Desc + logoutSuccessDesc *prometheus.Desc logoutMessageDesc *prometheus.Desc ) @@ -67,6 +95,32 @@ func init() { powerUpstreamDesc = prometheus.NewDesc(prefix+"upstream_power_dBmV", "Power", upstreamLabels, nil) rangingStatusUpstreamDesc = prometheus.NewDesc(prefix+"upstream_ranging_status_info", "Ranging status", append(upstreamLabels, "status"), nil) + firewallStatusDesc = prometheus.NewDesc(prefix+"firewall_status_info", "Firewall status", []string{"firewall_status"}, nil) + lanIPv4Desc = prometheus.NewDesc(prefix+"lan_ip4_info", "LAN IPv4 info", []string{"lan_ip4"}, nil) + lanModeDesc = prometheus.NewDesc(prefix+"lan_mode_info", "LAN mode info", []string{"mode"}, nil) + lanGatewayDesc = prometheus.NewDesc(prefix+"lan_gateway_info", "LAN gateway info", []string{"lan_gateway"}, nil) + lanDhcpEnabledDesc = prometheus.NewDesc(prefix+"lan_dhcp_enabled_bool", "LAN DHCP enabled info", nil, nil) + lanMacDesc = prometheus.NewDesc(prefix+"lan_mac_address_info", "LAN MAC address", []string{"mac_address"}, nil) + lanPortStatusDesc = prometheus.NewDesc(prefix+"lan_port_up_bool", "LAN port status", []string{"port"}, nil) + lanPortSpeedDesc = prometheus.NewDesc(prefix+"lan_port_speed_bits_per_second", "LAN port speed in bits/second", []string{"port"}, nil) + wlanEnabledDesc = prometheus.NewDesc(prefix+"wlan_enabled_bool", "WLAN enabled info", []string{"frequency"}, nil) + wlanChannelDesc = prometheus.NewDesc(prefix+"wlan_channel", "WLAN channel", []string{"frequency"}, nil) + wlanBandwidthDesc = prometheus.NewDesc(prefix+"wlan_bandwidth_hertz", "WLAN bandwidth in Hertz", []string{"frequency"}, nil) + wlanMaxSpeedDesc = prometheus.NewDesc(prefix+"wlan_max_speed_bits_per_second", "Max WLAN speed in bits/seconds", []string{"frequency"}, nil) + wlanSsidDesc = prometheus.NewDesc(prefix+"wlan_ssid_info", "SSID information", []string{"frequency", "ssid"}, nil) + wlanMacAddressDesc = prometheus.NewDesc(prefix+"wlan_mac_address_info", "WLAN MAC address", []string{"frequency", "mac_address"}, nil) + wlanSecurityDesc = prometheus.NewDesc(prefix+"wlan_security_info", "WLAN security", []string{"frequency", "security_info"}, nil) + dnsEntriesCountDesc = prometheus.NewDesc(prefix+"dns_entries_count", "DNS Entries count", nil, nil) + aftrDesc = prometheus.NewDesc(prefix+"aftr_info", "AFTR gateway information", []string{"aftr"}, nil) + seralnumberDesc = prometheus.NewDesc(prefix+"serialnumber_info", "Serial number information", []string{"serial_number"}, nil) + firmwareVersionDesc = prometheus.NewDesc(prefix+"firmwareversion_info", "Firmware vresion information", []string{"firmware_version"}, nil) + hardwareTypeDesc = prometheus.NewDesc(prefix+"hardware_type_info", "Hardware type information", []string{"hardware_type"}, nil) + uptimeDesc = prometheus.NewDesc(prefix+"uptime_seconds", "Uptime in seconds", nil, nil) + internetIPv4Desc = prometheus.NewDesc(prefix+"internet_ip4_info", "Internet IPv4", []string{"ip4"}, nil) + delegatedPrefixDesc = prometheus.NewDesc(prefix+"delegated_prefix_info", "Delegated prefix information", []string{"prefix"}, nil) + ipAddressRTDesc = prometheus.NewDesc(prefix+"ip_address_rt_info", "IP address RT", []string{"ip"}, nil) + ipPrefixClassDesc = prometheus.NewDesc(prefix+"ip_prefix_class_info", "IP prefix class info", []string{"prefix_class"}, nil) + logoutSuccessDesc = prometheus.NewDesc(prefix+"logout_success_bool", "1 if the logout was successfull", nil, nil) logoutMessageDesc = prometheus.NewDesc(prefix+"logout_message_info", "Logout message returned by the web interface", []string{"message"}, nil) } @@ -96,6 +150,32 @@ func (c *Collector) Describe(ch chan<- *prometheus.Desc) { ch <- powerUpstreamDesc ch <- rangingStatusUpstreamDesc + ch <- firewallStatusDesc + ch <- lanIPv4Desc + ch <- lanModeDesc + ch <- lanGatewayDesc + ch <- lanDhcpEnabledDesc + ch <- lanMacDesc + ch <- lanPortStatusDesc + ch <- lanPortSpeedDesc + ch <- wlanEnabledDesc + ch <- wlanChannelDesc + ch <- wlanBandwidthDesc + ch <- wlanMaxSpeedDesc + ch <- wlanSsidDesc + ch <- wlanMacAddressDesc + ch <- wlanSecurityDesc + ch <- dnsEntriesCountDesc + ch <- aftrDesc + ch <- seralnumberDesc + ch <- firmwareVersionDesc + ch <- hardwareTypeDesc + ch <- uptimeDesc + ch <- internetIPv4Desc + ch <- delegatedPrefixDesc + ch <- ipAddressRTDesc + ch <- ipPrefixClassDesc + ch <- logoutSuccessDesc ch <- logoutMessageDesc } @@ -117,6 +197,9 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(defaultPasswordDesc, prometheus.GaugeValue, bool2float64(loginresponse.Data.DefaultPassword == "Yes")) docsisStatusResponse, err := c.Station.GetDocsisStatus() + if err != nil { + fmt.Println(err.Error()) + } if err == nil && docsisStatusResponse.Data != nil { for _, downstreamChannel := range docsisStatusResponse.Data.Downstream { labels := []string{downstreamChannel.Id, downstreamChannel.ChannelId, downstreamChannel.Fft, downstreamChannel.ChannelType} @@ -143,6 +226,52 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) { } } + stationStatusResponse, err := c.Station.GetStationStatus() + if err != nil { + log.With("error", err.Error()).Error("Failed to get station status") + } else if stationStatusResponse.Data != nil { + ch <- prometheus.MustNewConstMetric(firewallStatusDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.FirewallStatus) + ch <- prometheus.MustNewConstMetric(lanIPv4Desc, prometheus.GaugeValue, 1, stationStatusResponse.Data.LanIpv4) + ch <- prometheus.MustNewConstMetric(lanModeDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.LanMode) + ch <- prometheus.MustNewConstMetric(lanGatewayDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.LanGateway) + ch <- prometheus.MustNewConstMetric(lanDhcpEnabledDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.LanDHCPstatus == "true")) + ch <- prometheus.MustNewConstMetric(lanMacDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.LanMAC) + ch <- prometheus.MustNewConstMetric(lanPortStatusDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.LanPortStatus1 == "Up"), "1") + ch <- prometheus.MustNewConstMetric(lanPortSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.LanPortSpeed1), "1") + ch <- prometheus.MustNewConstMetric(lanPortStatusDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.LanPortStatus2 == "Up"), "2") + ch <- prometheus.MustNewConstMetric(lanPortSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.LanPortSpeed2), "2") + ch <- prometheus.MustNewConstMetric(lanPortStatusDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.LanPortStatus3 == "Up"), "3") + ch <- prometheus.MustNewConstMetric(lanPortSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.LanPortSpeed3), "3") + ch <- prometheus.MustNewConstMetric(lanPortStatusDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.LanPortStatus4 == "Up"), "4") + ch <- prometheus.MustNewConstMetric(lanPortSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.LanPortSpeed4), "4") + ch <- prometheus.MustNewConstMetric(wlanEnabledDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.WifiStatus == "true"), "2.4 GHz") + ch <- prometheus.MustNewConstMetric(wlanChannelDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.Channel), "2.4 GHz") + ch <- prometheus.MustNewConstMetric(wlanBandwidthDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.Bandwidth)*10e9, "2.4 GHz") + ch <- prometheus.MustNewConstMetric(wlanMaxSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.MaxSpeed)*10e8, "2.4 GHz") + ch <- prometheus.MustNewConstMetric(wlanSsidDesc, prometheus.GaugeValue, 1, "2.4 GHz", stationStatusResponse.Data.Ssid) + ch <- prometheus.MustNewConstMetric(wlanMacAddressDesc, prometheus.GaugeValue, 1, "2.4 GHz", stationStatusResponse.Data.MacAddress) + ch <- prometheus.MustNewConstMetric(wlanSecurityDesc, prometheus.GaugeValue, 1, "2.4 GHz", stationStatusResponse.Data.Security) + ch <- prometheus.MustNewConstMetric(wlanEnabledDesc, prometheus.GaugeValue, bool2float64(stationStatusResponse.Data.WifiStatus5 == "true"), "5 GHz") + ch <- prometheus.MustNewConstMetric(wlanChannelDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.Channel5), "5 GHz") + ch <- prometheus.MustNewConstMetric(wlanBandwidthDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.Bandwidth5)*10e9, "5 GHz") + ch <- prometheus.MustNewConstMetric(wlanMaxSpeedDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.MaxSpeed5)*10e8, "5 GHz") + ch <- prometheus.MustNewConstMetric(wlanSsidDesc, prometheus.GaugeValue, 1, "5 GHz", stationStatusResponse.Data.Ssid5) + ch <- prometheus.MustNewConstMetric(wlanMacAddressDesc, prometheus.GaugeValue, 1, "5 GHz", stationStatusResponse.Data.MacAddress5) + ch <- prometheus.MustNewConstMetric(wlanSecurityDesc, prometheus.GaugeValue, 1, "5 GHz", stationStatusResponse.Data.Security5) + ch <- prometheus.MustNewConstMetric(dnsEntriesCountDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.DnsEntries)) + ch <- prometheus.MustNewConstMetric(aftrDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.AFTR) + ch <- prometheus.MustNewConstMetric(seralnumberDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.Serialnumber) + ch <- prometheus.MustNewConstMetric(firmwareVersionDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.FirmwareVersion) + ch <- prometheus.MustNewConstMetric(hardwareTypeDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.HardwareType) + ch <- prometheus.MustNewConstMetric(uptimeDesc, prometheus.GaugeValue, parse2float(stationStatusResponse.Data.Uptime)) + ch <- prometheus.MustNewConstMetric(internetIPv4Desc, prometheus.GaugeValue, 1, stationStatusResponse.Data.InternetIpv4) + ch <- prometheus.MustNewConstMetric(delegatedPrefixDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.DelegatedPrefix) + for _, ipAddressRT := range stationStatusResponse.Data.IPAddressRT { + ch <- prometheus.MustNewConstMetric(ipAddressRTDesc, prometheus.GaugeValue, 1, ipAddressRT) + } + ch <- prometheus.MustNewConstMetric(ipPrefixClassDesc, prometheus.GaugeValue, 1, stationStatusResponse.Data.IpPrefixClass) + } + logoutresponse, err := c.Station.Logout() if logoutresponse != nil { ch <- prometheus.MustNewConstMetric(logoutMessageDesc, prometheus.GaugeValue, 1, logoutresponse.Message) diff --git a/main.go b/main.go index 9e8f074..6e933ab 100644 --- a/main.go +++ b/main.go @@ -17,12 +17,18 @@ var ( showVersion = flag.Bool("version", false, "Print version and exit") listenAddress = flag.String("web.listen-address", "[::]:9420", "Address to listen on") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics") + logLevel = flag.String("log.level", "info", "Logging level") vodafoneStationUrl = flag.String("vodafone.station-url", "http://192.168.0.1", "Vodafone station URL. For bridge mode this is 192.168.100.1 (note: Configure a route if using bridge mode)") vodafoneStationPassword = flag.String("vodafone.station-password", "How is the default password calculated? mhmm", "Password for logging into the Vodafone station") ) func main() { flag.Parse() + err := log.Base().SetLevel(*logLevel) + if err != nil { + fmt.Println("Invalid log level") + os.Exit(2) + } if *showVersion { fmt.Println("vodafone-station-exporter")