diff --git a/pkg/collectors/contexts/contexts.go b/pkg/collectors/contexts/contexts.go index 3cd4873f..21b0a2df 100644 --- a/pkg/collectors/contexts/contexts.go +++ b/pkg/collectors/contexts/contexts.go @@ -5,14 +5,19 @@ package contexts import ( "fmt" + corev1 "k8s.io/api/core/v1" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" ) const ( - PTPNamespace = "openshift-ptp" - PTPPodNamePrefix = "linuxptp-daemon-" - PTPContainer = "linuxptp-daemon-container" - GPSContainer = "gpsd" + PTPNamespace = "openshift-ptp" + PTPPodNamePrefix = "linuxptp-daemon-" + PTPContainer = "linuxptp-daemon-container" + GPSContainer = "gpsd" + NetlinkDebugPod = "ptp-dpll-netlink-debug-pod" + NetlinkDebugContainer = "ptp-dpll-netlink-debug-container" + NetlinkDebugContainerImage = "quay.io/jnunez/tools:dpll9.2_dev" ) func GetPTPDaemonContext(clientset *clients.Clientset) (clients.ExecContext, error) { @@ -22,3 +27,24 @@ func GetPTPDaemonContext(clientset *clients.Clientset) (clients.ExecContext, err } return ctx, nil } + +func GetNetlinkContext(clientset *clients.Clientset) (*clients.ContainerCreationExecContext, error) { + ctx := clients.NewContainerCreationExecContext( + clientset, + PTPNamespace, + NetlinkDebugPod, + NetlinkDebugContainer, + NetlinkDebugContainerImage, + map[string]string{}, + []string{"sleep", "inf"}, + &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + // // Requires NET_ADMIN: having (NET_RAW + NET_BIND_SERVICE + NET_BROADCAST) does not work + // Add: []corev1.Capability{"NET_ADMIN"}, + Add: []corev1.Capability{"ALL", "NET_ADMIN"}, + }, + }, + true, + ) + return ctx, nil +} diff --git a/pkg/collectors/devices/dpll.go b/pkg/collectors/devices/dpll_fs.go similarity index 75% rename from pkg/collectors/devices/dpll.go rename to pkg/collectors/devices/dpll_fs.go index 7e122485..4c7695dd 100644 --- a/pkg/collectors/devices/dpll.go +++ b/pkg/collectors/devices/dpll_fs.go @@ -19,7 +19,7 @@ const ( unitConversionFactor = 100 ) -type DevDPLLInfo struct { +type DevFilesystemDPLLInfo struct { Timestamp string `fetcherKey:"date" json:"timestamp"` EECState string `fetcherKey:"dpll_0_state" json:"eecstate"` PPSState string `fetcherKey:"dpll_1_state" json:"state"` @@ -27,7 +27,7 @@ type DevDPLLInfo struct { } // AnalyserJSON returns the json expected by the analysers -func (dpllInfo *DevDPLLInfo) GetAnalyserFormat() ([]*callbacks.AnalyserFormatType, error) { +func (dpllInfo *DevFilesystemDPLLInfo) GetAnalyserFormat() ([]*callbacks.AnalyserFormatType, error) { formatted := callbacks.AnalyserFormatType{ ID: "dpll/time-error", Data: map[string]any{ @@ -41,14 +41,14 @@ func (dpllInfo *DevDPLLInfo) GetAnalyserFormat() ([]*callbacks.AnalyserFormatTyp } var ( - dpllFetcher map[string]*fetcher.Fetcher + dpllFSFetcher map[string]*fetcher.Fetcher ) func init() { - dpllFetcher = make(map[string]*fetcher.Fetcher) + dpllFSFetcher = make(map[string]*fetcher.Fetcher) } -func postProcessDPLL(result map[string]string) (map[string]any, error) { +func postProcessDPLLFilesystem(result map[string]string) (map[string]any, error) { processedResult := make(map[string]any) offset, err := strconv.ParseFloat(result["dpll_1_offset"], 32) if err != nil { @@ -58,9 +58,9 @@ func postProcessDPLL(result map[string]string) (map[string]any, error) { return processedResult, nil } -// BuildDPLLInfoFetcher popluates the fetcher required for +// BuildFilesystemDPLLInfoFetcher popluates the fetcher required for // collecting the DPLLInfo -func BuildDPLLInfoFetcher(interfaceName string) error { //nolint:dupl // Further dedup risks be too abstract or fragile +func BuildFilesystemDPLLInfoFetcher(interfaceName string) error { //nolint:dupl // Further dedup risks be too abstract or fragile fetcherInst, err := fetcher.FetcherFactory( []*clients.Cmd{dateCmd}, []fetcher.AddCommandArgs{ @@ -85,21 +85,21 @@ func BuildDPLLInfoFetcher(interfaceName string) error { //nolint:dupl // Further log.Errorf("failed to create fetcher for dpll: %s", err.Error()) return fmt.Errorf("failed to create fetcher for dpll: %w", err) } - dpllFetcher[interfaceName] = fetcherInst - fetcherInst.SetPostProcessor(postProcessDPLL) + dpllFSFetcher[interfaceName] = fetcherInst + fetcherInst.SetPostProcessor(postProcessDPLLFilesystem) return nil } -// GetDevDPLLInfo returns the device DPLL info for an interface. -func GetDevDPLLInfo(ctx clients.ContainerContext, interfaceName string) (DevDPLLInfo, error) { - dpllInfo := DevDPLLInfo{} - fetcherInst, fetchedInstanceOk := dpllFetcher[interfaceName] +// GetDevDPLLFilesystemInfo returns the device DPLL info for an interface. +func GetDevDPLLFilesystemInfo(ctx clients.ExecContext, interfaceName string) (DevFilesystemDPLLInfo, error) { + dpllInfo := DevFilesystemDPLLInfo{} + fetcherInst, fetchedInstanceOk := dpllFSFetcher[interfaceName] if !fetchedInstanceOk { - err := BuildDPLLInfoFetcher(interfaceName) + err := BuildFilesystemDPLLInfoFetcher(interfaceName) if err != nil { return dpllInfo, err } - fetcherInst, fetchedInstanceOk = dpllFetcher[interfaceName] + fetcherInst, fetchedInstanceOk = dpllFSFetcher[interfaceName] if !fetchedInstanceOk { return dpllInfo, errors.New("failed to create fetcher for DPLLInfo") } @@ -112,7 +112,7 @@ func GetDevDPLLInfo(ctx clients.ContainerContext, interfaceName string) (DevDPLL return dpllInfo, nil } -func IsDPLLFileSystemPresent(ctx clients.ContainerContext, interfaceName string) (bool, error) { +func IsDPLLFileSystemPresent(ctx clients.ExecContext, interfaceName string) (bool, error) { fetcherInst, err := fetcher.FetcherFactory( []*clients.Cmd{}, []fetcher.AddCommandArgs{ diff --git a/pkg/collectors/devices/dpll_test.go b/pkg/collectors/devices/dpll_fs_test.go similarity index 97% rename from pkg/collectors/devices/dpll_test.go rename to pkg/collectors/devices/dpll_fs_test.go index f1daa775..9215a72e 100644 --- a/pkg/collectors/devices/dpll_test.go +++ b/pkg/collectors/devices/dpll_fs_test.go @@ -56,7 +56,7 @@ var _ = Describe("NewContainerContext", func() { ctx, err := clients.NewContainerContext(clientset, "TestNamespace", "Test", "TestContainer") Expect(err).NotTo(HaveOccurred()) - info, err := devices.GetDevDPLLInfo(ctx, "aFakeInterface") + info, err := devices.GetDevDPLLFilesystemInfo(ctx, "aFakeInterface") Expect(err).NotTo(HaveOccurred()) Expect(info.Timestamp).To(Equal("2023-06-16T11:49:47.0584Z")) Expect(info.EECState).To(Equal(eecState)) diff --git a/pkg/collectors/devices/dpll_netlink.go b/pkg/collectors/devices/dpll_netlink.go new file mode 100644 index 00000000..8b11c834 --- /dev/null +++ b/pkg/collectors/devices/dpll_netlink.go @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package devices + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + + log "github.com/sirupsen/logrus" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" +) + +type DevNetlinkDPLLInfo struct { + Timestamp string `fetcherKey:"date" json:"timestamp"` + EECState string `fetcherKey:"eec" json:"eecstate"` + PPSState string `fetcherKey:"pps" json:"state"` +} + +// AnalyserJSON returns the json expected by the analysers +func (dpllInfo *DevNetlinkDPLLInfo) GetAnalyserFormat() ([]*callbacks.AnalyserFormatType, error) { + formatted := callbacks.AnalyserFormatType{ + ID: "dpll/states", + Data: map[string]any{ + "timestamp": dpllInfo.Timestamp, + "eecstate": dpllInfo.EECState, + "state": dpllInfo.PPSState, + }, + } + return []*callbacks.AnalyserFormatType{&formatted}, nil +} + +type NetlinkEntry struct { + LockStatus string `json:"lock-status"` //nolint:tagliatelle // not my choice + Driver string `json:"module-name"` //nolint:tagliatelle // not my choice + ClockType string `json:"type"` //nolint:tagliatelle // not my choice + ClockID int64 `json:"clock-id"` //nolint:tagliatelle // not my choice + ID int `json:"id"` //nolint:tagliatelle // not my choice +} + +var ( + dpllNetlinkFetcher map[int64]*fetcher.Fetcher + dpllClockIDFetcher map[string]*fetcher.Fetcher +) + +func init() { + dpllNetlinkFetcher = make(map[int64]*fetcher.Fetcher) + dpllClockIDFetcher = make(map[string]*fetcher.Fetcher) +} + +func buildPostProcessDPLLNetlink(clockID int64) fetcher.PostProcessFuncType { + return func(result map[string]string) (map[string]any, error) { + processedResult := make(map[string]any) + + entries := make([]NetlinkEntry, 0) + cleaned := strings.ReplaceAll(result["dpll-netlink"], "'", "\"") + log.Info("dpll ", cleaned) + err := json.Unmarshal([]byte(cleaned), &entries) + if err != nil { + log.Errorf("Failed to unmarshal netlink output: %s", err.Error()) + } + + log.Info("entries: ", entries) + for _, entry := range entries { + if entry.ClockID == clockID { + processedResult[entry.ClockType] = entry.LockStatus + } + } + return processedResult, nil + } +} + +// BuildDPLLInfoFetcher popluates the fetcher required for +// collecting the DPLLInfo +func BuildDPLLNetlinkInfoFetcher(clockID int64) error { //nolint:dupl // Further dedup risks be too abstract or fragile + fetcherInst, err := fetcher.FetcherFactory( + []*clients.Cmd{dateCmd}, + []fetcher.AddCommandArgs{ + { + Key: "dpll-netlink", + Command: "/linux/tools/net/ynl/cli.py --spec /linux/Documentation/netlink/specs/dpll.yaml --dump device-get", + Trim: true, + }, + }, + ) + if err != nil { + log.Errorf("failed to create fetcher for dpll: %s", err.Error()) + return fmt.Errorf("failed to create fetcher for dpll: %w", err) + } + dpllNetlinkFetcher[clockID] = fetcherInst + fetcherInst.SetPostProcessor(buildPostProcessDPLLNetlink(clockID)) + return nil +} + +// GetDevDPLLInfo returns the device DPLL info for an interface. +func GetDevDPLLNetlinkInfo(ctx clients.ExecContext, clockID int64) (DevNetlinkDPLLInfo, error) { + dpllInfo := DevNetlinkDPLLInfo{} + fetcherInst, fetchedInstanceOk := dpllNetlinkFetcher[clockID] + if !fetchedInstanceOk { + err := BuildDPLLNetlinkInfoFetcher(clockID) + if err != nil { + return dpllInfo, err + } + fetcherInst, fetchedInstanceOk = dpllNetlinkFetcher[clockID] + if !fetchedInstanceOk { + return dpllInfo, errors.New("failed to create fetcher for DPLLInfo using netlink interface") + } + } + err := fetcherInst.Fetch(ctx, &dpllInfo) + if err != nil { + log.Debugf("failed to fetch dpllInfo %s", err.Error()) + return dpllInfo, fmt.Errorf("failed to fetch dpllInfo %w", err) + } + return dpllInfo, nil +} + +func BuildClockIDFetcher(interfaceName string) error { + fetcherInst, err := fetcher.FetcherFactory( + []*clients.Cmd{dateCmd}, + []fetcher.AddCommandArgs{ + { + Key: "dpll-netlink-clock-id", + Command: fmt.Sprintf( + `export IFNAME=%s; export BUSID=$(readlink /sys/class/net/$IFNAME/device | xargs basename | cut -d ':' -f 2,3);`+ + ` echo $(("16#$(lspci -v | grep $BUSID -A 20 |grep 'Serial Number' | awk '{print $NF}' | tr -d '-')"))`, + interfaceName, + ), + Trim: true, + }, + }, + ) + if err != nil { + log.Errorf("failed to create fetcher for dpll: %s", err.Error()) + return fmt.Errorf("failed to create fetcher for dpll: %w", err) + } + fetcherInst.SetPostProcessor(postProcessDPLLNetlinkClockID) + dpllClockIDFetcher[interfaceName] = fetcherInst + return nil +} + +func postProcessDPLLNetlinkClockID(result map[string]string) (map[string]any, error) { + processedResult := make(map[string]any) + clockID, err := strconv.ParseInt(result["dpll-netlink-clock-id"], 10, 64) + if err != nil { + return processedResult, fmt.Errorf("failed to parse int for clock id: %w", err) + } + processedResult["clockID"] = clockID + return processedResult, nil +} + +type NetlinkClockID struct { + Timestamp string `fetcherKey:"date" json:"timestamp"` + ClockID int64 `fetcherKey:"clockID" json:"clockId"` +} + +func GetClockID(ctx clients.ExecContext, interfaceName string) (NetlinkClockID, error) { + clockID := NetlinkClockID{} + fetcherInst, fetchedInstanceOk := dpllClockIDFetcher[interfaceName] + if !fetchedInstanceOk { + err := BuildClockIDFetcher(interfaceName) + if err != nil { + return clockID, err + } + fetcherInst, fetchedInstanceOk = dpllClockIDFetcher[interfaceName] + if !fetchedInstanceOk { + return clockID, errors.New("failed to create fetcher for DPLLInfo using netlink interface") + } + } + err := fetcherInst.Fetch(ctx, &clockID) + if err != nil { + log.Debugf("failed to fetch netlink clockID %s", err.Error()) + return clockID, fmt.Errorf("failed to fetch netlink clockID %w", err) + } + return clockID, nil +} diff --git a/pkg/collectors/dpll_collector.go b/pkg/collectors/dpll_collector.go index 12c6c25a..1503ea44 100644 --- a/pkg/collectors/dpll_collector.go +++ b/pkg/collectors/dpll_collector.go @@ -3,108 +3,31 @@ package collectors import ( - "errors" "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + log "github.com/sirupsen/logrus" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" ) -type DPLLCollector struct { - callback callbacks.Callback - ctx clients.ContainerContext - interfaceName string - running bool - pollInterval int -} - const ( DPLLCollectorName = "DPLL" - DPLLInfo = "dpll-info" ) -func (dpll *DPLLCollector) GetPollInterval() int { - return dpll.pollInterval -} - -func (dpll *DPLLCollector) IsAnnouncer() bool { - return false -} - -// Start sets up the collector so it is ready to be polled -func (dpll *DPLLCollector) Start() error { - dpll.running = true - return nil -} - -// polls for the dpll info then passes it to the callback -func (dpll *DPLLCollector) poll() error { - dpllInfo, err := devices.GetDevDPLLInfo(dpll.ctx, dpll.interfaceName) - - if err != nil { - return fmt.Errorf("failed to fetch %s %w", DPLLInfo, err) - } - err = dpll.callback.Call(&dpllInfo, DPLLInfo) - if err != nil { - return fmt.Errorf("callback failed %w", err) - } - return nil -} - -// Poll collects information from the cluster then -// calls the callback.Call to allow that to persist it -func (dpll *DPLLCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { - defer func() { - wg.Done() - }() - errorsToReturn := make([]error, 0) - err := dpll.poll() - if err != nil { - errorsToReturn = append(errorsToReturn, err) - } - resultsChan <- PollResult{ - CollectorName: DPLLCollectorName, - Errors: errorsToReturn, - } -} - -// CleanUp stops a running collector -func (dpll *DPLLCollector) CleanUp() error { - dpll.running = false - return nil -} - // Returns a new DPLLCollector from the CollectionConstuctor Factory func NewDPLLCollector(constructor *CollectionConstructor) (Collector, error) { ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { - return &DPLLCollector{}, fmt.Errorf("failed to create DPLLCollector: %w", err) + return &DPLLNetlinkCollector{}, fmt.Errorf("failed to create DPLLCollector: %w", err) } - err = devices.BuildDPLLInfoFetcher(constructor.PTPInterface) - if err != nil { - return &DPLLCollector{}, fmt.Errorf("failed to build fetcher for DPLLInfo %w", err) + dpllFSExists, err := devices.IsDPLLFileSystemPresent(ctx, constructor.PTPInterface) + log.Debug("DPLL FS exists: ", dpllFSExists) + if dpllFSExists && err == nil { + return NewDPLLFilesystemCollector(constructor) + } else { + return NewDPLLNetlinkCollector(constructor) } - - collector := DPLLCollector{ - interfaceName: constructor.PTPInterface, - ctx: ctx, - running: false, - callback: constructor.Callback, - pollInterval: constructor.PollInterval, - } - - dpllFSExists, err := devices.IsDPLLFileSystemPresent(collector.ctx, collector.interfaceName) - if err != nil { - return &collector, utils.NewRequirementsNotMetError(fmt.Errorf("checking for the DPLL filesystem failed: %w", err)) - } - if !dpllFSExists { - return &collector, utils.NewRequirementsNotMetError(errors.New("filesystem with DPLL stats not present")) - } - - return &collector, nil } func init() { diff --git a/pkg/collectors/dpll_collector_fs.go b/pkg/collectors/dpll_collector_fs.go new file mode 100644 index 00000000..cc03a645 --- /dev/null +++ b/pkg/collectors/dpll_collector_fs.go @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package collectors + +import ( + "fmt" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" +) + +type DPLLFilesystemCollector struct { + callback callbacks.Callback + ctx clients.ExecContext + interfaceName string + running bool + pollInterval int +} + +const ( + DPLLFilesystemCollectorName = "DPLL-Filesystem" + DPLLInfo = "dpll-info-fs" +) + +func (dpll *DPLLFilesystemCollector) GetPollInterval() int { + return dpll.pollInterval +} + +func (dpll *DPLLFilesystemCollector) IsAnnouncer() bool { + return false +} + +// Start sets up the collector so it is ready to be polled +func (dpll *DPLLFilesystemCollector) Start() error { + dpll.running = true + return nil +} + +// polls for the dpll info then passes it to the callback +func (dpll *DPLLFilesystemCollector) poll() error { + dpllInfo, err := devices.GetDevDPLLFilesystemInfo(dpll.ctx, dpll.interfaceName) + + if err != nil { + return fmt.Errorf("failed to fetch %s %w", DPLLInfo, err) + } + err = dpll.callback.Call(&dpllInfo, DPLLInfo) + if err != nil { + return fmt.Errorf("callback failed %w", err) + } + return nil +} + +// Poll collects information from the cluster then +// calls the callback.Call to allow that to persist it +func (dpll *DPLLFilesystemCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { + defer func() { + wg.Done() + }() + errorsToReturn := make([]error, 0) + err := dpll.poll() + if err != nil { + errorsToReturn = append(errorsToReturn, err) + } + resultsChan <- PollResult{ + CollectorName: DPLLFilesystemCollectorName, + Errors: errorsToReturn, + } +} + +// CleanUp stops a running collector +func (dpll *DPLLFilesystemCollector) CleanUp() error { + dpll.running = false + return nil +} + +// Returns a new DPLLFilesystemCollector from the CollectionConstuctor Factory +func NewDPLLFilesystemCollector(constructor *CollectionConstructor) (Collector, error) { + ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) + if err != nil { + return &DPLLFilesystemCollector{}, fmt.Errorf("failed to create DPLLFilesystemCollector: %w", err) + } + err = devices.BuildFilesystemDPLLInfoFetcher(constructor.PTPInterface) + if err != nil { + return &DPLLFilesystemCollector{}, fmt.Errorf("failed to build fetcher for DPLLInfo %w", err) + } + + collector := DPLLFilesystemCollector{ + interfaceName: constructor.PTPInterface, + ctx: ctx, + running: false, + callback: constructor.Callback, + pollInterval: constructor.PollInterval, + } + return &collector, nil +} diff --git a/pkg/collectors/dpll_collector_netlink.go b/pkg/collectors/dpll_collector_netlink.go new file mode 100644 index 00000000..adfdce1c --- /dev/null +++ b/pkg/collectors/dpll_collector_netlink.go @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package collectors + +import ( + "fmt" + + log "github.com/sirupsen/logrus" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" +) + +type DPLLNetlinkCollector struct { + callback callbacks.Callback + ctx *clients.ContainerCreationExecContext + interfaceName string + clockID int64 + running bool + pollInterval int +} + +const ( + DPLLNetlinkCollectorName = "DPLL-Netlink" + DPLLNetlinkInfo = "dpll-info-nl" +) + +func (dpll *DPLLNetlinkCollector) GetPollInterval() int { + return dpll.pollInterval +} + +func (dpll *DPLLNetlinkCollector) IsAnnouncer() bool { + return false +} + +// Start sets up the collector so it is ready to be polled +func (dpll *DPLLNetlinkCollector) Start() error { + dpll.running = true + err := dpll.ctx.CreatePodAndWaitForStart() + if err != nil { + return fmt.Errorf("dpll netlink collector failed to start pod: %w", err) + } + log.Debug("dpll.interfaceName: ", dpll.interfaceName) + log.Debug("dpll.ctx: ", dpll.ctx) + clockIDStuct, err := devices.GetClockID(dpll.ctx, dpll.interfaceName) + if err != nil { + return fmt.Errorf("dpll netlink collector failed to find clock id: %w", err) + } + log.Debug("clockIDStuct.ClockID: ", clockIDStuct.ClockID) + err = devices.BuildDPLLNetlinkInfoFetcher(clockIDStuct.ClockID) + if err != nil { + return fmt.Errorf("failed to build fetcher for DPLLInfo %w", err) + } + dpll.clockID = clockIDStuct.ClockID + log.Debug("dpll.clockID Really?: ", dpll.clockID) + return nil +} + +// polls for the dpll info then passes it to the callback +func (dpll *DPLLNetlinkCollector) poll() error { + dpllInfo, err := devices.GetDevDPLLNetlinkInfo(dpll.ctx, dpll.clockID) + + if err != nil { + return fmt.Errorf("failed to fetch %s %w", DPLLInfo, err) + } + err = dpll.callback.Call(&dpllInfo, DPLLInfo) + if err != nil { + return fmt.Errorf("callback failed %w", err) + } + return nil +} + +// Poll collects information from the cluster then +// calls the callback.Call to allow that to persist it +func (dpll *DPLLNetlinkCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { + defer func() { + wg.Done() + }() + errorsToReturn := make([]error, 0) + err := dpll.poll() + if err != nil { + errorsToReturn = append(errorsToReturn, err) + } + resultsChan <- PollResult{ + CollectorName: DPLLNetlinkCollectorName, + Errors: errorsToReturn, + } +} + +// CleanUp stops a running collector +func (dpll *DPLLNetlinkCollector) CleanUp() error { + dpll.running = false + err := dpll.ctx.DeletePodAndWait() + if err != nil { + return fmt.Errorf("dpll netlink collector failed to clean up: %w", err) + } + return nil +} + +// Returns a new DPLLNetlinkCollector from the CollectionConstuctor Factory +func NewDPLLNetlinkCollector(constructor *CollectionConstructor) (Collector, error) { + ctx, err := contexts.GetNetlinkContext(constructor.Clientset) + if err != nil { + return &DPLLNetlinkCollector{}, fmt.Errorf("failed to create DPLLNetlinkCollector: %w", err) + } + + collector := DPLLNetlinkCollector{ + interfaceName: constructor.PTPInterface, + ctx: ctx, + running: false, + callback: constructor.Callback, + pollInterval: constructor.PollInterval, + } + + return &collector, nil +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 2b298897..b21dd779 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -186,6 +186,7 @@ func (runner *CollectorRunner) start() { for collectorName, collector := range runner.collectorInstances { log.Debugf("start collector %v", collector) err := collector.Start() + log.Info("collector:", collectorName, " start error: ", err) utils.IfErrorExitOrPanic(err) log.Debugf("Spawning collector: %v", collector)