You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ro...@apache.org on 2018/12/14 04:03:35 UTC

[trafficcontrol] branch master updated (9df709e -> 10d3225)

This is an automated email from the ASF dual-hosted git repository.

rob pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git.


    from 9df709e  updated cachegroup api to include cachegroup fallbacks. updated docum… (#3110)
     new 3619985  Add Traffic Monitor Disk Support
     new 1e91b01  Fixing review comments
     new e5640d8  Change unmarshal error to return the error up instead of logging
     new 10d3225  Change default location of backups to be /opt/traffic_monitor. Trying to use pwd can result in issues when run from systemd

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 docs/source/development/traffic_monitor.rst |  8 +++
 traffic_monitor/config/config.go            | 22 ++++++++
 traffic_monitor/manager/manager.go          |  2 +-
 traffic_monitor/manager/opsconfig.go        | 26 +++++++++
 traffic_monitor/towrap/towrap.go            | 82 +++++++++++++++++++++++++----
 5 files changed, 130 insertions(+), 10 deletions(-)


[trafficcontrol] 03/04: Change unmarshal error to return the error up instead of logging

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit e5640d82c06329e06e37d3b8392216c30833e58f
Author: Evan Zelkowitz <19...@users.noreply.github.com>
AuthorDate: Wed Dec 12 11:04:28 2018 -0700

    Change unmarshal error to return the error up instead of logging
---
 traffic_monitor/towrap/towrap.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/traffic_monitor/towrap/towrap.go b/traffic_monitor/towrap/towrap.go
index f6a9d4d..d81ba69 100644
--- a/traffic_monitor/towrap/towrap.go
+++ b/traffic_monitor/towrap/towrap.go
@@ -331,8 +331,8 @@ func (s TrafficOpsSessionThreadsafe) trafficMonitorConfigMapRaw(cdn string) (*tc
 
 		log.Errorln("Error getting configMap from traffic_ops, backup file exists, reading from file")
 		json := jsoniter.ConfigFastest
-		if err = json.Unmarshal(b, &configMap); err != nil {
-			log.Errorln("Error unmarshaling JSON from TMConfigBackupFile")
+		if err := json.Unmarshal(b, &configMap); err != nil {
+			return nil, errors.New("unmarhsalling backup file monitoring.json: " + err.Error())
 		}
 		return configMap, err
 	}


[trafficcontrol] 04/04: Change default location of backups to be /opt/traffic_monitor. Trying to use pwd can result in issues when run from systemd

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit 10d3225cf63970afaf548bdaa9582117019c46a1
Author: Evan Zelkowitz <19...@users.noreply.github.com>
AuthorDate: Thu Dec 13 08:40:07 2018 -0700

    Change default location of backups to be /opt/traffic_monitor. Trying to use pwd can result in issues when run from systemd
---
 traffic_monitor/config/config.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/traffic_monitor/config/config.go b/traffic_monitor/config/config.go
index 7ec8fe1..c55e065 100644
--- a/traffic_monitor/config/config.go
+++ b/traffic_monitor/config/config.go
@@ -41,9 +41,9 @@ const (
 	//StaticFileDir is the directory that contains static html and js files.
 	StaticFileDir = "/opt/traffic_monitor/static/"
 	//CrConfigBackupFile is the default file name to store the last crconfig
-	CRConfigBackupFile = "crconfig.backup"
+	CRConfigBackupFile = "/opt/traffic_monitor/crconfig.backup"
 	//TmConfigBackupFile is the default file name to store the last tmconfig
-	TMConfigBackupFile = "tmconfig.backup"
+	TMConfigBackupFile = "/opt/traffic_monitor/tmconfig.backup"
 )
 
 // Config is the configuration for the application. It includes myriad data, such as polling intervals and log locations.


[trafficcontrol] 01/04: Add Traffic Monitor Disk Support

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit 3619985a3ee3c476ee34607c0b8e21fcd9568a9a
Author: Evan Zelkowitz <19...@users.noreply.github.com>
AuthorDate: Wed Nov 21 11:02:35 2018 -0700

    Add Traffic Monitor Disk Support
    
    With these changes traffic monitor will create TM and CR backup files on disk. If TO is unreachable and these files exist then it will pull its data from these files. Any time a new valid one is available it will write them back to disk. On
    startup TM will still follow its exponential backoff scheme but once it hits the max it will create a non-authenticated TO session so that we can use the disk files. If at any point TO comes back up then TM will attempt to authenticate and
    continue as normal
---
 docs/source/development/traffic_monitor.rst |  8 +++
 traffic_monitor/config/config.go            | 22 ++++++++
 traffic_monitor/manager/manager.go          |  2 +-
 traffic_monitor/manager/opsconfig.go        | 26 ++++++++++
 traffic_monitor/towrap/towrap.go            | 79 +++++++++++++++++++++++++----
 5 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/docs/source/development/traffic_monitor.rst b/docs/source/development/traffic_monitor.rst
index 4be0fdb..a835d44 100644
--- a/docs/source/development/traffic_monitor.rst
+++ b/docs/source/development/traffic_monitor.rst
@@ -192,6 +192,14 @@ Shared Data
 -----------
 Processed and aggregated data must be shared between the end of the stat and health processing pipelines, and HTTP requests. The CSP paradigm of idiomatic Go does not work efficiently with storing and sharing state. While not idiomatic Go, shared mutexed data structures are faster and simpler than CSP manager microthreads for each data object. Traffic Monitor has many thread-safe shared data types and objects. All shared data objects can be seen in ``manager/manager.go:Start()``, where t [...]
 
+Disk Backup
+------------
+The traffic monitor config and CR config are both stored as backup files (tmconfig.backup and crconfig.backup or what ever you set the values to in the config file). This allows the monitor to come up and continue serving even if traffic ops 
+is down.  These files are updated any time a valid config is received from traffic ops, so if traffic ops goes down and the monitor is restarted it can still serve the previous data.  These files can also be manually edited and the changes 
+will be reloaded in to traffic monitor so that if traffic ops is down or unreachable for an extended period of time manual updates can be done. If on initial startup trafficops is unavailable then traffic monitor will continue through it's 
+exponential backoff until it hits the max retry interval, at that point it will create an un-authenticated trafficops session and use the data from disk. It will still poll trafficops for updates though and if it successfully gets through 
+then it will login at that point.
+
 Formatting Conventions
 ======================
 Go code should be formatted with ``gofmt``. See also ``CONTRIBUTING.md``.
diff --git a/traffic_monitor/config/config.go b/traffic_monitor/config/config.go
index 8017950..4f38343 100644
--- a/traffic_monitor/config/config.go
+++ b/traffic_monitor/config/config.go
@@ -40,6 +40,10 @@ const (
 	LogLocationNull = "null"
 	//StaticFileDir is the directory that contains static html and js files.
 	StaticFileDir = "/opt/traffic_monitor/static/"
+	//CrConfigBackupFile is the default file name to store the last crconfig
+	CrConfigBackupFile = "crconfig.backup"
+	//TmConfigBackupFile is the default file name to store the last tmconfig
+	TmConfigBackupFile = "tmconfig.backup"
 )
 
 // Config is the configuration for the application. It includes myriad data, such as polling intervals and log locations.
@@ -68,6 +72,9 @@ type Config struct {
 	CRConfigHistoryCount         uint64        `json:"crconfig_history_count"`
 	TrafficOpsMinRetryInterval   time.Duration `json:"-"`
 	TrafficOpsMaxRetryInterval   time.Duration `json:"-"`
+	CrConfigBackupFile           string        `json:"crconfig_backup_file"`
+	TmConfigBackupFile           string        `json:"tmconfig_backup_file"`
+	TrafficOpsDiskRetryMax       uint64        `json:"-"`
 }
 
 func (c Config) ErrorLog() log.LogLocation   { return log.LogLocation(c.LogLocationError) }
@@ -102,6 +109,9 @@ var DefaultConfig = Config{
 	CRConfigHistoryCount:         20000,
 	TrafficOpsMinRetryInterval:   100 * time.Millisecond,
 	TrafficOpsMaxRetryInterval:   60000 * time.Millisecond,
+	CrConfigBackupFile:           CrConfigBackupFile,
+	TmConfigBackupFile:           TmConfigBackupFile,
+	TrafficOpsDiskRetryMax:       2,
 }
 
 // MarshalJSON marshals custom millisecond durations. Aliasing inspired by http://choly.ca/post/go-json-marshalling/
@@ -152,6 +162,9 @@ func (c *Config) UnmarshalJSON(data []byte) error {
 		ServeWriteTimeoutMs            *uint64 `json:"serve_write_timeout_ms"`
 		TrafficOpsMinRetryIntervalMs   *uint64 `json:"traffic_ops_min_retry_interval_ms"`
 		TrafficOpsMaxRetryIntervalMs   *uint64 `json:"traffic_ops_max_retry_interval_ms"`
+		TrafficOpsDiskRetryMax         *uint64 `json:"traffic_ops_disk_retry_max"`
+		CrConfigBackupFile             *string `json:"crconfig_backup_file"`
+		TmConfigBackupFile             *string `json:"tmconfig_backup_file"`
 		*Alias
 	}{
 		Alias: (*Alias)(c),
@@ -200,6 +213,15 @@ func (c *Config) UnmarshalJSON(data []byte) error {
 	if aux.TrafficOpsMaxRetryIntervalMs != nil {
 		c.TrafficOpsMaxRetryInterval = time.Duration(*aux.TrafficOpsMaxRetryIntervalMs) * time.Millisecond
 	}
+	if aux.TrafficOpsDiskRetryMax != nil {
+		c.TrafficOpsDiskRetryMax = *aux.TrafficOpsDiskRetryMax
+	}
+	if aux.CrConfigBackupFile != nil {
+		c.CrConfigBackupFile = *aux.CrConfigBackupFile
+	}
+	if aux.TmConfigBackupFile != nil {
+		c.TmConfigBackupFile = *aux.TmConfigBackupFile
+	}
 	return nil
 }
 
diff --git a/traffic_monitor/manager/manager.go b/traffic_monitor/manager/manager.go
index 6ba9dc9..f6f0c0f 100644
--- a/traffic_monitor/manager/manager.go
+++ b/traffic_monitor/manager/manager.go
@@ -43,7 +43,7 @@ import (
 // Start starts the poller and handler goroutines
 //
 func Start(opsConfigFile string, cfg config.Config, appData config.StaticAppData, trafficMonitorConfigFileName string) error {
-	toSession := towrap.ITrafficOpsSession(towrap.NewTrafficOpsSessionThreadsafe(nil, cfg.CRConfigHistoryCount))
+	toSession := towrap.ITrafficOpsSession(towrap.NewTrafficOpsSessionThreadsafe(nil, cfg.CRConfigHistoryCount, cfg))
 
 	localStates := peer.NewCRStatesThreadsafe() // this is the local state as discoverer by this traffic_monitor
 	fetchCount := threadsafe.NewUint()          // note this is the number of individual caches fetched from, not the number of times all the caches were polled.
diff --git a/traffic_monitor/manager/opsconfig.go b/traffic_monitor/manager/opsconfig.go
index 7b34bcd..6da71bd 100644
--- a/traffic_monitor/manager/opsconfig.go
+++ b/traffic_monitor/manager/opsconfig.go
@@ -20,9 +20,12 @@ package manager
  */
 
 import (
+	"crypto/tls"
 	"fmt"
 	"io/ioutil"
 	"net"
+	"net/http"
+	"net/http/cookiejar"
 	"time"
 
 	"golang.org/x/sys/unix"
@@ -138,6 +141,7 @@ func StartOpsConfigManager(
 		trafficOpsRequestTimeout := time.Second * time.Duration(10)
 		var realToSession *to.Session
 		var toAddr net.Addr
+		var toLoginCount uint64
 
 		// fixed an issue here where traffic_monitor loops forever, doing nothing useful if traffic_ops is down,
 		// and would never logging in again.  since traffic_monitor  is just starting up here, keep retrying until traffic_ops is reachable and a session can be established.
@@ -154,6 +158,28 @@ func StartOpsConfigManager(
 				duration := backoff.BackoffDuration()
 				log.Errorf("retrying in %v\n", duration)
 				time.Sleep(duration)
+
+				if toSession.BackupFileExists() && (toLoginCount >= cfg.TrafficOpsDiskRetryMax) {
+					jar, err := cookiejar.New(nil)
+					if err != nil {
+						log.Errorf("Err getting cookiejar")
+						continue
+					}
+
+					realToSession = to.NewSession(newOpsConfig.Username, newOpsConfig.Password, newOpsConfig.Url, staticAppData.UserAgent, &http.Client{
+						Timeout: trafficOpsRequestTimeout,
+						Transport: &http.Transport{
+							TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+						},
+						Jar: jar,
+					}, useCache)
+					toSession.Set(realToSession)
+					// At this point we have a valid 'dummy' session. This will allow us to pull from disk but will also retry when TO comes up
+					log.Errorf("error instantiating Session with traffic_ops, backup disk files exist, creating empty traffic_ops session to read")
+					break
+				}
+
+				toLoginCount++
 				continue
 			} else {
 				toSession.Set(realToSession)
diff --git a/traffic_monitor/towrap/towrap.go b/traffic_monitor/towrap/towrap.go
index a017945..fc1cc9e 100644
--- a/traffic_monitor/towrap/towrap.go
+++ b/traffic_monitor/towrap/towrap.go
@@ -22,12 +22,15 @@ package towrap
 import (
 	"errors"
 	"fmt"
+	"io/ioutil"
+	"os"
 	"strconv"
 	"sync"
 	"time"
 
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_monitor/config"
 	"github.com/apache/trafficcontrol/traffic_ops/client"
 
 	"github.com/json-iterator/go"
@@ -47,6 +50,7 @@ type ITrafficOpsSession interface {
 	DeliveryServices() ([]tc.DeliveryService, error)
 	CacheGroups() ([]tc.CacheGroupNullable, error)
 	CRConfigHistory() []CRConfigStat
+	BackupFileExists() bool
 }
 
 var ErrNilSession = fmt.Errorf("nil session")
@@ -63,6 +67,15 @@ type ByteMapCache struct {
 	m     *sync.RWMutex
 }
 
+func (s TrafficOpsSessionThreadsafe) BackupFileExists() bool {
+	if _, err := os.Stat(s.CrConfigBackupFile); !os.IsNotExist(err) {
+		if _, err = os.Stat(s.TmConfigBackupFile); !os.IsNotExist(err) {
+			return true
+		}
+	}
+	return false
+}
+
 func NewByteMapCache() ByteMapCache {
 	return ByteMapCache{m: &sync.RWMutex{}, cache: &map[string]ByteTime{}}
 }
@@ -148,15 +161,17 @@ type CRConfigStat struct {
 
 // TrafficOpsSessionThreadsafe provides access to the Traffic Ops client safe for multiple goroutines. This fulfills the ITrafficOpsSession interface.
 type TrafficOpsSessionThreadsafe struct {
-	session      **client.Session // pointer-to-pointer, because we're given a pointer from the Traffic Ops package, and we don't want to copy it.
-	m            *sync.Mutex
-	lastCRConfig ByteMapCache
-	crConfigHist CRConfigHistoryThreadsafe
+	session            **client.Session // pointer-to-pointer, because we're given a pointer from the Traffic Ops package, and we don't want to copy it.
+	m                  *sync.Mutex
+	lastCRConfig       ByteMapCache
+	crConfigHist       CRConfigHistoryThreadsafe
+	CrConfigBackupFile string
+	TmConfigBackupFile string
 }
 
 // NewTrafficOpsSessionThreadsafe returns a new threadsafe TrafficOpsSessionThreadsafe wrapping the given `Session`.
-func NewTrafficOpsSessionThreadsafe(s *client.Session, crConfigHistoryLimit uint64) TrafficOpsSessionThreadsafe {
-	return TrafficOpsSessionThreadsafe{session: &s, m: &sync.Mutex{}, lastCRConfig: NewByteMapCache(), crConfigHist: NewCRConfigHistoryThreadsafe(crConfigHistoryLimit)}
+func NewTrafficOpsSessionThreadsafe(s *client.Session, crConfigHistoryLimit uint64, cfg config.Config) TrafficOpsSessionThreadsafe {
+	return TrafficOpsSessionThreadsafe{session: &s, m: &sync.Mutex{}, lastCRConfig: NewByteMapCache(), crConfigHist: NewCRConfigHistoryThreadsafe(crConfigHistoryLimit), CrConfigBackupFile: cfg.CrConfigBackupFile, TmConfigBackupFile: cfg.TmConfigBackupFile}
 }
 
 // Set sets the internal Traffic Ops session. This is safe for multiple goroutines, being aware they will race.
@@ -229,16 +244,36 @@ func (s *TrafficOpsSessionThreadsafe) CRConfigValid(crc *tc.CRConfig, cdn string
 
 // CRConfigRaw returns the CRConfig from the Traffic Ops. This is safe for multiple goroutines.
 func (s TrafficOpsSessionThreadsafe) CRConfigRaw(cdn string) ([]byte, error) {
+
 	ss := s.get()
+
+	var b []byte
+	var err error
+	var remoteAddr string
+	var reqInf client.ReqInf
+
 	if ss == nil {
 		return nil, ErrNilSession
+	} else {
+		b, reqInf, err = ss.GetCRConfig(cdn)
+		if err == nil {
+			remoteAddr = reqInf.RemoteAddr.String()
+			ioutil.WriteFile(s.CrConfigBackupFile, b, 0644)
+		} else {
+			if s.BackupFileExists() {
+				b, _ = ioutil.ReadFile(s.CrConfigBackupFile)
+				remoteAddr = "127.0.0.1"
+				log.Errorln("Error getting CRConfig from traffic_ops, backup file exists, reading from file")
+			} else {
+				return nil, ErrNilSession
+			}
+		}
 	}
-	b, reqInf, err := ss.GetCRConfig(cdn)
 
-	hist := &CRConfigStat{time.Now(), reqInf.RemoteAddr.String(), tc.CRConfigStats{}, err}
+	hist := &CRConfigStat{time.Now(), remoteAddr, tc.CRConfigStats{}, err}
 	defer s.crConfigHist.Add(hist)
 
-	if err != nil {
+	if err != nil && remoteAddr != "127.0.0.1" {
 		return b, err
 	}
 
@@ -277,8 +312,30 @@ func (s TrafficOpsSessionThreadsafe) trafficMonitorConfigMapRaw(cdn string) (*tc
 	if ss == nil {
 		return nil, ErrNilSession
 	}
-	configMap, _, error := ss.GetTrafficMonitorConfigMap(cdn)
-	return configMap, error
+	var configMap *tc.TrafficMonitorConfigMap
+	var err error
+
+	configMap, _, err = ss.GetTrafficMonitorConfigMap(cdn)
+	if configMap != nil {
+		json := jsoniter.ConfigFastest
+		data, err := json.Marshal(*configMap)
+		if err == nil {
+			ioutil.WriteFile(s.TmConfigBackupFile, data, 0644)
+		}
+	} else {
+		if s.BackupFileExists() {
+			b, _ := ioutil.ReadFile(s.TmConfigBackupFile)
+			log.Errorln("Error getting configMap from traffic_ops, backup file exists, reading from file")
+			json := jsoniter.ConfigFastest
+			err = json.Unmarshal(b, &configMap)
+			if err != nil {
+				log.Warnf("Error unmarshaling TmConfigBackupFile, ", err)
+			}
+
+		}
+	}
+
+	return configMap, err
 }
 
 // TrafficMonitorConfigMap returns the Traffic Monitor config map from the Traffic Ops. This is safe for multiple goroutines.


[trafficcontrol] 02/04: Fixing review comments

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit 1e91b01c6abaffede05e50f0668cad5fe6f345cf
Author: Evan Zelkowitz <19...@users.noreply.github.com>
AuthorDate: Tue Dec 11 09:47:13 2018 -0700

    Fixing review comments
---
 traffic_monitor/config/config.go | 24 ++++++------
 traffic_monitor/towrap/towrap.go | 81 ++++++++++++++++++++++------------------
 2 files changed, 56 insertions(+), 49 deletions(-)

diff --git a/traffic_monitor/config/config.go b/traffic_monitor/config/config.go
index 4f38343..7ec8fe1 100644
--- a/traffic_monitor/config/config.go
+++ b/traffic_monitor/config/config.go
@@ -41,9 +41,9 @@ const (
 	//StaticFileDir is the directory that contains static html and js files.
 	StaticFileDir = "/opt/traffic_monitor/static/"
 	//CrConfigBackupFile is the default file name to store the last crconfig
-	CrConfigBackupFile = "crconfig.backup"
+	CRConfigBackupFile = "crconfig.backup"
 	//TmConfigBackupFile is the default file name to store the last tmconfig
-	TmConfigBackupFile = "tmconfig.backup"
+	TMConfigBackupFile = "tmconfig.backup"
 )
 
 // Config is the configuration for the application. It includes myriad data, such as polling intervals and log locations.
@@ -72,8 +72,8 @@ type Config struct {
 	CRConfigHistoryCount         uint64        `json:"crconfig_history_count"`
 	TrafficOpsMinRetryInterval   time.Duration `json:"-"`
 	TrafficOpsMaxRetryInterval   time.Duration `json:"-"`
-	CrConfigBackupFile           string        `json:"crconfig_backup_file"`
-	TmConfigBackupFile           string        `json:"tmconfig_backup_file"`
+	CRConfigBackupFile           string        `json:"crconfig_backup_file"`
+	TMConfigBackupFile           string        `json:"tmconfig_backup_file"`
 	TrafficOpsDiskRetryMax       uint64        `json:"-"`
 }
 
@@ -109,8 +109,8 @@ var DefaultConfig = Config{
 	CRConfigHistoryCount:         20000,
 	TrafficOpsMinRetryInterval:   100 * time.Millisecond,
 	TrafficOpsMaxRetryInterval:   60000 * time.Millisecond,
-	CrConfigBackupFile:           CrConfigBackupFile,
-	TmConfigBackupFile:           TmConfigBackupFile,
+	CRConfigBackupFile:           CRConfigBackupFile,
+	TMConfigBackupFile:           TMConfigBackupFile,
 	TrafficOpsDiskRetryMax:       2,
 }
 
@@ -163,8 +163,8 @@ func (c *Config) UnmarshalJSON(data []byte) error {
 		TrafficOpsMinRetryIntervalMs   *uint64 `json:"traffic_ops_min_retry_interval_ms"`
 		TrafficOpsMaxRetryIntervalMs   *uint64 `json:"traffic_ops_max_retry_interval_ms"`
 		TrafficOpsDiskRetryMax         *uint64 `json:"traffic_ops_disk_retry_max"`
-		CrConfigBackupFile             *string `json:"crconfig_backup_file"`
-		TmConfigBackupFile             *string `json:"tmconfig_backup_file"`
+		CRConfigBackupFile             *string `json:"crconfig_backup_file"`
+		TMConfigBackupFile             *string `json:"tmconfig_backup_file"`
 		*Alias
 	}{
 		Alias: (*Alias)(c),
@@ -216,11 +216,11 @@ func (c *Config) UnmarshalJSON(data []byte) error {
 	if aux.TrafficOpsDiskRetryMax != nil {
 		c.TrafficOpsDiskRetryMax = *aux.TrafficOpsDiskRetryMax
 	}
-	if aux.CrConfigBackupFile != nil {
-		c.CrConfigBackupFile = *aux.CrConfigBackupFile
+	if aux.CRConfigBackupFile != nil {
+		c.CRConfigBackupFile = *aux.CRConfigBackupFile
 	}
-	if aux.TmConfigBackupFile != nil {
-		c.TmConfigBackupFile = *aux.TmConfigBackupFile
+	if aux.TMConfigBackupFile != nil {
+		c.TMConfigBackupFile = *aux.TMConfigBackupFile
 	}
 	return nil
 }
diff --git a/traffic_monitor/towrap/towrap.go b/traffic_monitor/towrap/towrap.go
index fc1cc9e..f6a9d4d 100644
--- a/traffic_monitor/towrap/towrap.go
+++ b/traffic_monitor/towrap/towrap.go
@@ -53,6 +53,8 @@ type ITrafficOpsSession interface {
 	BackupFileExists() bool
 }
 
+const localHostIP = "127.0.0.1"
+
 var ErrNilSession = fmt.Errorf("nil session")
 
 // TODO rename CRConfigCacheObj
@@ -68,8 +70,8 @@ type ByteMapCache struct {
 }
 
 func (s TrafficOpsSessionThreadsafe) BackupFileExists() bool {
-	if _, err := os.Stat(s.CrConfigBackupFile); !os.IsNotExist(err) {
-		if _, err = os.Stat(s.TmConfigBackupFile); !os.IsNotExist(err) {
+	if _, err := os.Stat(s.CRConfigBackupFile); !os.IsNotExist(err) {
+		if _, err = os.Stat(s.TMConfigBackupFile); !os.IsNotExist(err) {
 			return true
 		}
 	}
@@ -165,13 +167,13 @@ type TrafficOpsSessionThreadsafe struct {
 	m                  *sync.Mutex
 	lastCRConfig       ByteMapCache
 	crConfigHist       CRConfigHistoryThreadsafe
-	CrConfigBackupFile string
-	TmConfigBackupFile string
+	CRConfigBackupFile string
+	TMConfigBackupFile string
 }
 
 // NewTrafficOpsSessionThreadsafe returns a new threadsafe TrafficOpsSessionThreadsafe wrapping the given `Session`.
 func NewTrafficOpsSessionThreadsafe(s *client.Session, crConfigHistoryLimit uint64, cfg config.Config) TrafficOpsSessionThreadsafe {
-	return TrafficOpsSessionThreadsafe{session: &s, m: &sync.Mutex{}, lastCRConfig: NewByteMapCache(), crConfigHist: NewCRConfigHistoryThreadsafe(crConfigHistoryLimit), CrConfigBackupFile: cfg.CrConfigBackupFile, TmConfigBackupFile: cfg.TmConfigBackupFile}
+	return TrafficOpsSessionThreadsafe{session: &s, m: &sync.Mutex{}, lastCRConfig: NewByteMapCache(), crConfigHist: NewCRConfigHistoryThreadsafe(crConfigHistoryLimit), CRConfigBackupFile: cfg.CRConfigBackupFile, TMConfigBackupFile: cfg.TMConfigBackupFile}
 }
 
 // Set sets the internal Traffic Ops session. This is safe for multiple goroutines, being aware they will race.
@@ -247,33 +249,35 @@ func (s TrafficOpsSessionThreadsafe) CRConfigRaw(cdn string) ([]byte, error) {
 
 	ss := s.get()
 
-	var b []byte
-	var err error
 	var remoteAddr string
-	var reqInf client.ReqInf
 
 	if ss == nil {
 		return nil, ErrNilSession
+	}
+
+	b, reqInf, err := ss.GetCRConfig(cdn)
+	if err == nil {
+		remoteAddr = reqInf.RemoteAddr.String()
+		ioutil.WriteFile(s.CRConfigBackupFile, b, 0644)
 	} else {
-		b, reqInf, err = ss.GetCRConfig(cdn)
-		if err == nil {
-			remoteAddr = reqInf.RemoteAddr.String()
-			ioutil.WriteFile(s.CrConfigBackupFile, b, 0644)
-		} else {
-			if s.BackupFileExists() {
-				b, _ = ioutil.ReadFile(s.CrConfigBackupFile)
-				remoteAddr = "127.0.0.1"
-				log.Errorln("Error getting CRConfig from traffic_ops, backup file exists, reading from file")
-			} else {
-				return nil, ErrNilSession
+		if s.BackupFileExists() {
+			b, err = ioutil.ReadFile(s.CRConfigBackupFile)
+			if err != nil {
+				err = errors.New("file Read Error: " + err.Error())
+				return nil, err
 			}
+			remoteAddr = localHostIP
+			log.Errorln("Error getting CRConfig from traffic_ops, backup file exists, reading from file")
+			err = nil
+		} else {
+			return nil, ErrNilSession
 		}
 	}
 
 	hist := &CRConfigStat{time.Now(), remoteAddr, tc.CRConfigStats{}, err}
 	defer s.crConfigHist.Add(hist)
 
-	if err != nil && remoteAddr != "127.0.0.1" {
+	if err != nil {
 		return b, err
 	}
 
@@ -312,29 +316,32 @@ func (s TrafficOpsSessionThreadsafe) trafficMonitorConfigMapRaw(cdn string) (*tc
 	if ss == nil {
 		return nil, ErrNilSession
 	}
-	var configMap *tc.TrafficMonitorConfigMap
-	var err error
 
-	configMap, _, err = ss.GetTrafficMonitorConfigMap(cdn)
-	if configMap != nil {
-		json := jsoniter.ConfigFastest
-		data, err := json.Marshal(*configMap)
-		if err == nil {
-			ioutil.WriteFile(s.TmConfigBackupFile, data, 0644)
+	configMap, _, err := ss.GetTrafficMonitorConfigMap(cdn)
+	if err != nil {
+		// Default error case, no backup file exists
+		if !s.BackupFileExists() {
+			return configMap, err
 		}
-	} else {
-		if s.BackupFileExists() {
-			b, _ := ioutil.ReadFile(s.TmConfigBackupFile)
-			log.Errorln("Error getting configMap from traffic_ops, backup file exists, reading from file")
-			json := jsoniter.ConfigFastest
-			err = json.Unmarshal(b, &configMap)
-			if err != nil {
-				log.Warnf("Error unmarshaling TmConfigBackupFile, ", err)
-			}
 
+		b, err := ioutil.ReadFile(s.TMConfigBackupFile)
+		if err != nil {
+			return nil, errors.New("reading TMConfigBackupFile: " + err.Error())
 		}
+
+		log.Errorln("Error getting configMap from traffic_ops, backup file exists, reading from file")
+		json := jsoniter.ConfigFastest
+		if err = json.Unmarshal(b, &configMap); err != nil {
+			log.Errorln("Error unmarshaling JSON from TMConfigBackupFile")
+		}
+		return configMap, err
 	}
 
+	json := jsoniter.ConfigFastest
+	data, err := json.Marshal(*configMap)
+	if err == nil {
+		ioutil.WriteFile(s.TMConfigBackupFile, data, 0644)
+	}
 	return configMap, err
 }