Skip to content

Commit 05339d0

Browse files
author
Saied Kazemi
authored
Run two TRC containers locally for MDA and regular traceroutes (#139)
* Run two TRC containers locally for MDA and regular traceroutes This commit contains changes for running two instances of the traceroute-caller container locally via docker-compose. One instance runs MDA traceroutes (scamper1 datatype) and the other instance runs regular traceroutes (scamper2 datatype). Changes tested locally with "go test -race" and also with "docker-compose".
1 parent 230155a commit 05339d0

File tree

6 files changed

+63
-14
lines changed

6 files changed

+63
-14
lines changed

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ RUN apt-get update && \
4343
apt-get clean && \
4444
rm -rf /var/lib/apt/lists/*
4545

46+
# Create /var/empty to avoid a race condition in scamper that results
47+
# in the following failure:
48+
# scamper_privsep_init: could not mkdir /var/empty: File exists
49+
RUN mkdir -p /var/empty && \
50+
chmod 555 /var/empty
51+
4652
# Bring the statically-linked traceroute-caller binary from the go build image.
4753
COPY --from=build_caller /go/bin/traceroute-caller /
4854

docker-compose.yaml

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ services:
1919
published: 9992
2020
protocol: tcp
2121
mode: bridge
22+
- target: 9993
23+
published: 9993
24+
protocol: tcp
25+
mode: bridge
2226
command:
2327
- -prometheusx.listen-address=:9990
2428
- -output=/local/tcpinfo
@@ -44,7 +48,7 @@ services:
4448
- -siteinfo.url=file:///testdata/annotations-incomplete.json
4549
- -hostname=mlab1-lga0t.mlab-sandbox.measurement-lab.org
4650

47-
traceroute-caller:
51+
trc-scamper1:
4852
build:
4953
context: .
5054
dockerfile: Dockerfile
@@ -65,11 +69,33 @@ services:
6569
- -IPCacheTimeout=1m
6670
- -IPCacheUpdatePeriod=10s
6771
- -hopannotation-output=/local/hopannotation1
72+
- -scamper.trace-type=mda
73+
- -traceroute-output=/local/scamper1
74+
- -scamper.timeout=30m
75+
- -scamper.tracelb-W=15
76+
- -scamper.tracelb-ptr=true
77+
78+
trc-scamper2:
79+
build:
80+
context: .
81+
dockerfile: Dockerfile
82+
volumes:
83+
- ./local:/local
84+
network_mode: "service:tcpinfo"
85+
deploy:
86+
# NOTE: traceroute-caller may fail on startup if it tries to read a
87+
# socket that the above services are not yet listening on.
88+
# So, allow restart.
89+
restart_policy:
90+
condition: any
91+
delay: 5s
92+
command:
93+
- -prometheusx.listen-address=:9993
94+
- -tcpinfo.eventsocket=/local/tcpevents.sock
95+
- -ipservice.sock=/local/uuid-annotator.sock
96+
- -IPCacheTimeout=1m
97+
- -IPCacheUpdatePeriod=10s
98+
- -hopannotation-output=/local/hopannotation1
6899
- -scamper.trace-type=regular
69100
- -traceroute-output=/local/scamper2
70101
- -scamper.timeout=10m
71-
# -scamper.trace-type=mda
72-
#- -traceroute-output=/local/scamper1
73-
#- -scamper.timeout=30m
74-
#- -scamper.tracelb-W=15
75-
#- -scamper.tracelb-ptr=false

hopannotation/hopannotation.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ var (
6464
hostname string
6565

6666
// Package testing aid.
67-
tickerDuration = int64(60 * 1000 * time.Millisecond) // ticker duration for cache resetter
68-
writeFile = ioutil.WriteFile
67+
tickerDuration = int64(60 * 1000 * time.Millisecond) // ticker duration for cache resetter
68+
writeFile = ioutil.WriteFile
69+
errInvalidConfig = errors.New("invalid context or hop annotation configuration")
6970
)
7071

7172
// HopAnnotation1 is the datatype that is written to the hop annotation file.
@@ -107,8 +108,8 @@ func init() {
107108
// passage of the midnight every minute to reset the cache. The goroutine
108109
// will terminate when the ctx is cancelled.
109110
func New(ctx context.Context, haCfg Config) (*HopCache, error) {
110-
if haCfg.AnnotatorClient == nil || haCfg.OutputPath == "" {
111-
return nil, fmt.Errorf("invalid hop annotation configuration: %+v", haCfg)
111+
if ctx == nil || haCfg.AnnotatorClient == nil || haCfg.OutputPath == "" {
112+
return nil, fmt.Errorf("%v: %+v", errInvalidConfig, haCfg)
112113
}
113114
hc := &HopCache{
114115
hops: make(map[string]bool, 10000), // based on observation

hopannotation/hopannotation_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ func newHopCache(ctx context.Context, t *testing.T, path string) (*HopCache, *fa
7676
}
7777

7878
func TestNew(t *testing.T) {
79+
// First check with invalid parameters.
80+
haCfg := Config{
81+
AnnotatorClient: nil,
82+
OutputPath: "",
83+
}
84+
if _, err := New(context.TODO(), haCfg); !strings.Contains(err.Error(), errInvalidConfig.Error()) {
85+
t.Fatalf("New() = %v, want %v", err, errInvalidConfig)
86+
}
87+
7988
// Change ticker duration to 100ms to avoid waiting a long time for
8089
// the resetter goroutine to notice passage of midnight or cancelled
8190
// context.

internal/triggertrace/triggertrace.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,13 @@ func (h *Handler) traceAnnotateAndArchive(ctx context.Context, dest Destination)
157157
log.Printf("failed to annotate some or all hops (errors: %+v)\n", allErrs)
158158
}
159159
if len(annotations) > 0 {
160-
h.HopAnnotator.WriteAnnotations(annotations, traceStartTime)
160+
allErrs := h.HopAnnotator.WriteAnnotations(annotations, traceStartTime)
161+
if allErrs != nil {
162+
log.Printf("failed to write some or all annotations due to the following error(s):\n")
163+
for _, err := range allErrs {
164+
log.Printf("error: %v\n", err)
165+
}
166+
}
161167
}
162168
}
163169

tracer/scamper.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ func (s *Scamper) CachedTrace(cookie, uuid string, t time.Time, cachedTrace []by
106106

107107
// Create and add the first line to the cached traceroute.
108108
newTrace := append(createMetaline(uuid, true, extractUUID(cachedTrace[:split])), cachedTrace[split+1:]...)
109-
return ioutil.WriteFile(filename, []byte(newTrace), 0666)
109+
// Make the file readable so it won't be overwritten.
110+
return ioutil.WriteFile(filename, []byte(newTrace), 0444)
110111
}
111112

112113
// DontTrace is called when a previous traceroute that we were waiting for
@@ -159,7 +160,7 @@ func runCmd(ctx context.Context, label string, cmd []string) ([]byte, error) {
159160
var outb, errb bytes.Buffer
160161
c.Stdout = &outb
161162
c.Stderr = &errb
162-
log.Printf("context %p: command %s started\n", ctx, strings.Join(cmd, " "))
163+
log.Printf("context %p: command started: %s\n", ctx, strings.Join(cmd, " "))
163164
start := time.Now()
164165
err := c.Run()
165166
latency := time.Since(start).Seconds()
@@ -179,7 +180,7 @@ func runCmd(ctx context.Context, label string, cmd []string) ([]byte, error) {
179180
return outb.Bytes(), err
180181
}
181182

182-
log.Printf("Command succeeded in context %p\n", ctx)
183+
log.Printf("context %p: command succeeded\n", ctx)
183184
traceTimeHistogram.WithLabelValues("success").Observe(latency)
184185
return outb.Bytes(), nil
185186
}

0 commit comments

Comments
 (0)