Skip to content

Commit

Permalink
fix recreation of metrics on edit or delete operation on ptpconfig
Browse files Browse the repository at this point in the history
Signed-off-by: Aneesh Puttur <aputtur@redhat.com>
  • Loading branch information
aneeshkp committed Mar 26, 2024
1 parent 38cb9bc commit a06d6ae
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 21 deletions.
49 changes: 35 additions & 14 deletions plugins/ptp_operator/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,26 @@ func (pt *PtpClockThreshold) SafeClose() (justClosed bool) {

// LinuxPTPConfigMapUpdate for ptp-conf update
type LinuxPTPConfigMapUpdate struct {
lock sync.RWMutex
UpdateCh chan bool
NodeProfiles []PtpProfile
appliedNodeProfileJSON []byte
profilePath string
intervalUpdate int
EventThreshold map[string]*PtpClockThreshold
PtpProcessOpts map[string]*PtpProcessOpts
PtpSettings map[string]map[string]string
DeleteConfigInProcess bool
lock sync.RWMutex
UpdateCh chan bool
NodeProfiles []PtpProfile
appliedNodeProfileJSON []byte
profilePath string
intervalUpdate int
EventThreshold map[string]*PtpClockThreshold
PtpProcessOpts map[string]*PtpProcessOpts
PtpSettings map[string]map[string]string
fileWatcherUpdateInProgress bool
}

// AppliedNodeProfileJSON ....
func (l *LinuxPTPConfigMapUpdate) AppliedNodeProfileJSON() []byte {
return l.appliedNodeProfileJSON
}

// SetAppliedNodeProfileJSON ...
func (l *LinuxPTPConfigMapUpdate) SetAppliedNodeProfileJSON(appliedNodeProfileJSON []byte) {
l.appliedNodeProfileJSON = appliedNodeProfileJSON
}

// NewLinuxPTPConfUpdate -- profile updater
Expand Down Expand Up @@ -206,13 +216,18 @@ func (l *LinuxPTPConfigMapUpdate) DeleteAllPTPThreshold() {
}
}

// UpdateDeleteConfigInProcess ... if config file is deleted delay config update reads
func (l *LinuxPTPConfigMapUpdate) UpdateDeleteConfigInProcess(delete bool) {
// FileWatcherUpdateInProgress ... if config file watcher delay config update reads
func (l *LinuxPTPConfigMapUpdate) FileWatcherUpdateInProgress(inProgress bool) {
l.lock.Lock()
l.DeleteConfigInProcess = delete
l.fileWatcherUpdateInProgress = inProgress
l.lock.Unlock()
}

// IsFileWatcherUpdateInProgress ... if config file watcher delay config update reads
func (l *LinuxPTPConfigMapUpdate) IsFileWatcherUpdateInProgress() bool {
return l.fileWatcherUpdateInProgress
}

func closeHoldover(t *PtpClockThreshold) {
defer func() {
if err := recover(); err != nil {
Expand Down Expand Up @@ -355,16 +370,22 @@ func (l *LinuxPTPConfigMapUpdate) WatchConfigMapUpdate(nodeName string, closeCh
select {
case <-tickerPull.C:
l.updatePtpConfig(nodeName)
return // only do it once until ptpconfig is found
case <-closeCh:
log.Info("signal received, shutting down")
return
}
}
}

// PushPtpConfigMapChanges ... push configMap updates
func (l *LinuxPTPConfigMapUpdate) PushPtpConfigMapChanges(nodeName string) {
l.updatePtpConfig(nodeName)
}

func (l *LinuxPTPConfigMapUpdate) updatePtpConfig(nodeName string) {
nodeProfile := filepath.Join(l.profilePath, nodeName)
if l.DeleteConfigInProcess {
if l.IsFileWatcherUpdateInProgress() {
log.Infof("delete action on config was detetcted; delaying updating ptpconfig")
return // wait until delete is completed
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/ptp_operator/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func (p *PTPEventManager) ExtractMetrics(msg string) {
profileName := ptp4lCfg.Profile

if !p.validLogToProcess(profileName, processName, len(ptp4lCfg.Interfaces)) {
log.Infof("skipped parsing %s", output)
return
}

Expand Down Expand Up @@ -335,7 +336,7 @@ func (p *PTPEventManager) processDownEvent(profileName, processName string, ptpS

func (p *PTPEventManager) validLogToProcess(profileName, processName string, iFaceSize int) bool {
if profileName == "" {
log.Errorf("ptp4l config does not have profile name, aborting. ")
log.Info("ptp4l config does not have profile name, skipping. ")
return false
}
if !p.hasHAProfile(profileName) && profileName != "" && iFaceSize == 0 { //TODO: Use PMC to update port and roles
Expand Down
2 changes: 1 addition & 1 deletion plugins/ptp_operator/metrics/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func DeletedPTPMetrics(clockType, processName, eventResourceName string) {
"process": processName, "node": ptpNodeName, "iface": eventResourceName})
}

// DeleteThresholdMetrics .. delete threshold metrics
// DeleteThresholdMetrics ... delete threshold metrics
func DeleteThresholdMetrics(profile string) {
Threshold.Delete(prometheus.Labels{
"threshold": "MinOffsetThreshold", "node": ptpNodeName, "profile": profile})
Expand Down
40 changes: 35 additions & 5 deletions plugins/ptp_operator/ptp_operator_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"os"
"strings"
"sync"
"time"

"k8s.io/utils/pointer"

Expand Down Expand Up @@ -105,7 +106,6 @@ func Start(wg *sync.WaitGroup, configuration *common.SCConfiguration, fn func(e
go listenToSocket(wg)
// watch for ptp any config updates
go eventManager.PtpConfigMapUpdates.WatchConfigMapUpdate(nodeName, configuration.CloseCh)

// watch and monitor ptp4l config file creation and deletion
// create a ptpConfigDir directory watcher for config changes
notifyConfigDirUpdates = make(chan *ptp4lconf.PtpConfigUpdate, 20) // max 20 profiles since all files will be deleted in reapply
Expand All @@ -114,6 +114,7 @@ func Start(wg *sync.WaitGroup, configuration *common.SCConfiguration, fn func(e
log.Errorf("cannot monitor ptp4l configuation folder at %s : %s", ptpConfigDir, err)
return err
}

// process ptp4l conf file updates under /var/run/ptp4l.X.conf
go processPtp4lConfigFileUpdates()

Expand Down Expand Up @@ -271,9 +272,19 @@ func getCurrentStatOverrideFn() func(e v2.Event, d *channel.DataChan) error {
}
}

// update interface and threshold details when ptpConfig change found
// these are updated when config file is created or deleted under /var/run folder
// update interface details and threshold details when ptpConfig change found.
// These are updated when config file is created or deleted under /var/run folder
// by linuxptp-daemon.
// issue to resolve: linuxptp-daemon-container will read ptpconfig and update ptpConfigMap
// the updates are incremental and file creation happens when ptpConfigMap is updated
// NOTE: there is delay between configmap updates and file creation
// FIRST ptpConfigMap created and then the daemon ticker when starting the process
// creates the files or deletes the file when process is stopped
// This routine tries to rely on file creation to detect ptp config updates
// and on file creation call ptpConfig updates
// on file deletion reset to read fresh ptpconfig updates
func processPtp4lConfigFileUpdates() {
fileModified := false
for {
select {
case ptpConfigEvent := <-notifyConfigDirUpdates:
Expand Down Expand Up @@ -362,13 +373,24 @@ func processPtp4lConfigFileUpdates() {
strings.Replace(cName, ptp4lProcessName, ts2PhcProcessName, 1), ts2PhcProcessName)
}
}
for key, np := range eventManager.PtpConfigMapUpdates.EventThreshold {
ptpMetrics.Threshold.With(prometheus.Labels{
"threshold": "MinOffsetThreshold", "node": eventManager.NodeName(), "profile": key}).Set(float64(np.MinOffsetThreshold))
ptpMetrics.Threshold.With(prometheus.Labels{
"threshold": "MaxOffsetThreshold", "node": eventManager.NodeName(), "profile": key}).Set(float64(np.MaxOffsetThreshold))
ptpMetrics.Threshold.With(prometheus.Labels{
"threshold": "HoldOverTimeout", "node": eventManager.NodeName(), "profile": key}).Set(float64(np.HoldOverTimeout))
}
case true: // ptp4l.X.conf is deleted ; how to prevent updates happening at same time
// delete metrics, ptp4l config is removed
// get config fileName
fileModified = true
eventManager.PtpConfigMapUpdates.FileWatcherUpdateInProgress(true)
log.Infof("delete ptp config %s at %s", *ptpConfigEvent.Name, time.Now())
ptpConfigFileName := ptpTypes.ConfigName(*ptpConfigEvent.Name)
ptp4lConfig := eventManager.GetPTPConfig(ptpConfigFileName)
log.Infof("deleting config %s with profile %s\n", *ptpConfigEvent.Name, ptp4lConfig.Profile)
eventManager.PtpConfigMapUpdates.UpdateDeleteConfigInProcess(true)

ptpStats := eventManager.GetStats(ptpConfigFileName)
// to avoid new one getting created , make a copy of this stats
ptpStats.SetConfigAsDeleted(true)
Expand Down Expand Up @@ -430,11 +452,19 @@ func processPtp4lConfigFileUpdates() {
// clean up process metrics
ptpMetrics.DeleteProcessStatusMetricsForConfig(eventManager.NodeName(), string(ptpConfigFileName), ptp4lProcessName, phc2sysProcessName)
ptpMetrics.DeleteProcessStatusMetricsForConfig(eventManager.NodeName(), strings.Replace(string(ptpConfigFileName), ptp4lProcessName, ts2PhcProcessName, 1), ts2PhcProcessName)
eventManager.PtpConfigMapUpdates.UpdateDeleteConfigInProcess(false)
}
case <-config.CloseCh:
fileWatcher.Close()
return
default:
// decision maker before ptpConfig map updates can be processes
if fileModified {
eventManager.PtpConfigMapUpdates.FileWatcherUpdateInProgress(false)
eventManager.PtpConfigMapUpdates.SetAppliedNodeProfileJSON([]byte{}) // reset ptpconfig dataset and update again
eventManager.PtpConfigMapUpdates.PushPtpConfigMapChanges(eventManager.NodeName())
fileModified = false
}

Check failure on line 467 in plugins/ptp_operator/ptp_operator_plugin.go

View workflow job for this annotation

GitHub Actions / Linting

unnecessary trailing newline (whitespace)
}
}
}
Expand Down

0 comments on commit a06d6ae

Please sign in to comment.