Skip to content

Commit 8fdddab

Browse files
authored
add example with lammps pvc (#66)
* add example with lammps pvc Signed-off-by: vsoch <[email protected]>
1 parent cf5fed5 commit 8fdddab

File tree

7 files changed

+117
-23
lines changed

7 files changed

+117
-23
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
apiVersion: flux-framework.org/v1alpha2
2+
kind: MetricSet
3+
metadata:
4+
labels:
5+
app.kubernetes.io/name: metricset
6+
app.kubernetes.io/instance: metricset-sample
7+
name: metricset-sample
8+
spec:
9+
# Number of pods for lammps (one launcher, the rest workers)
10+
pods: 4
11+
12+
# Keep interactive so we can decide when to quit
13+
logging:
14+
interactive: true
15+
16+
metrics:
17+
18+
# Running more scaled lammps is our main goal
19+
- name: app-lammps
20+
21+
# This has intel mpi on rocky linux, per suggested by Google
22+
image: ghcr.io/converged-computing/metric-lammps-intel-mpi:rocky
23+
24+
options:
25+
command: lmp -v x 2 -v y 2 -v z 2 -in in.reaxc.hns -nocite
26+
workdir: /opt/lammps/examples/reaxff/HNS
27+
soleTenancy: "true"
28+
29+
# Add on hpctoolkit, will mount a volume and wrap lammps
30+
addons:
31+
32+
- name: volume-pvc
33+
options:
34+
name: data
35+
claimName: data
36+
path: /storage
37+
readOnly: "false"
38+
39+
- name: perf-hpctoolkit
40+
options:
41+
mount: /opt/mnt
42+
# This allows us to ask where is the event blocked / taking more time
43+
events: "-e REALTIME@10000"
44+
45+
# Use a custom container here too (we have for rocky and ubuntu)
46+
image: ghcr.io/converged-computing/metric-hpctoolkit-view:rocky
47+
48+
# hpcrun needs to have mpirun in front of hpcrun <command> e.g.,
49+
# mpirun <MPI args> hpcrun <hpcrun args> <app> <app args>
50+
prefix: /opt/intel/mpi/2021.8.0/bin/mpirun --hostfile ./hostlist.txt -np 4 -map-by ppr:1:node
51+
52+
# Ensure the working directory is consistent
53+
workdir: /opt/lammps/examples/reaxff/HNS
54+
55+
# Target container for entrypoint addition is the launcher, not workers
56+
containerTarget: launcher

pkg/addons/addons.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,34 +65,34 @@ type AddonBase struct {
6565
mapOptions map[string]map[string]intstr.IntOrString
6666
}
6767

68-
func (b AddonBase) SetOptions(metric *api.MetricAddon) {}
69-
func (b AddonBase) CustomizeEntrypoints([]*specs.ContainerSpec, []*jobset.ReplicatedJob) {}
68+
func (b *AddonBase) SetOptions(metric *api.MetricAddon) {}
69+
func (b *AddonBase) CustomizeEntrypoints([]*specs.ContainerSpec, []*jobset.ReplicatedJob) {}
7070

71-
func (b AddonBase) Validate() bool {
71+
func (b *AddonBase) Validate() bool {
7272
return true
7373
}
74-
func (b AddonBase) AssembleContainers() []specs.ContainerSpec {
74+
func (b *AddonBase) AssembleContainers() []specs.ContainerSpec {
7575
return []specs.ContainerSpec{}
7676
}
7777

7878
// Assemble Volumes (for now) just generates one
79-
func (b AddonBase) AssembleVolumes() []specs.VolumeSpec {
79+
func (b *AddonBase) AssembleVolumes() []specs.VolumeSpec {
8080
return []specs.VolumeSpec{}
8181
}
8282

83-
func (b AddonBase) Description() string {
83+
func (b *AddonBase) Description() string {
8484
return b.Summary
8585
}
86-
func (b AddonBase) Name() string {
86+
func (b *AddonBase) Name() string {
8787
return b.Identifier
8888
}
89-
func (b AddonBase) Options() map[string]intstr.IntOrString {
89+
func (b *AddonBase) Options() map[string]intstr.IntOrString {
9090
return b.options
9191
}
92-
func (b AddonBase) ListOptions() map[string][]intstr.IntOrString {
92+
func (b *AddonBase) ListOptions() map[string][]intstr.IntOrString {
9393
return b.listOptions
9494
}
95-
func (b AddonBase) MapOptions() map[string]map[string]intstr.IntOrString {
95+
func (b *AddonBase) MapOptions() map[string]map[string]intstr.IntOrString {
9696
return b.mapOptions
9797
}
9898

pkg/addons/commands.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616
jobset "sigs.k8s.io/jobset/api/jobset/v1alpha2"
1717
)
1818

19+
const (
20+
commandsName = "commands"
21+
perfCommandsName = "perf-commands"
22+
)
23+
1924
// Perf addon expects the same command structure, but adds sys caps for trace and admin
2025
type PerfAddon struct {
2126
CommandAddon
@@ -37,6 +42,11 @@ func (a *PerfAddon) CustomizeEntrypoints(
3742
}
3843
}
3944

45+
func (a *PerfAddon) SetOptions(metric *api.MetricAddon) {
46+
a.Identifier = perfCommandsName
47+
a.SetSharedCommandOptions(metric)
48+
}
49+
4050
// addContainerCaps adds capabilities to a container spec
4151
func (a *PerfAddon) addContainerCaps(
4252
cs []*specs.ContainerSpec,
@@ -92,8 +102,13 @@ func (m CommandAddon) Family() string {
92102
return AddonFamilyApplication
93103
}
94104

95-
// Set custom options / attributes for the metric
96105
func (a *CommandAddon) SetOptions(metric *api.MetricAddon) {
106+
a.Identifier = commandsName
107+
a.SetSharedCommandOptions(metric)
108+
}
109+
110+
// Set custom options / attributes for the metric
111+
func (a *CommandAddon) SetSharedCommandOptions(metric *api.MetricAddon) {
97112
target, ok := metric.Options["target"]
98113
if ok {
99114
a.target = target.StrVal
@@ -213,14 +228,14 @@ func init() {
213228

214229
// Config map volume type
215230
base := AddonBase{
216-
Identifier: "commands",
231+
Identifier: commandsName,
217232
Summary: "customize a metric's entrypoints",
218233
}
219234
app := CommandAddon{AddonBase: base}
220235
Register(&app)
221236

222237
base = AddonBase{
223-
Identifier: "perf-commands",
238+
Identifier: perfCommandsName,
224239
Summary: "customize a metric's entrypoints expecting performance tracing (adding ptrace and admin caps)",
225240
}
226241
cmd := CommandAddon{AddonBase: base}

pkg/addons/hpctoolkit.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import (
2525
// hpcstruct hpctoolkit-sleep-measurements
2626
// hpcprof hpctoolkit-sleep-measurements
2727
// hpcviewer ./hpctoolkit-lmp-database
28+
const (
29+
hpctoolkitIdentifier = "perf-hpctoolkit"
30+
)
2831

2932
type HPCToolkit struct {
3033
ApplicationAddon
@@ -121,6 +124,7 @@ func (a *HPCToolkit) SetOptions(metric *api.MetricAddon) {
121124
a.volumeName = "hpctoolkit"
122125
a.output = "hpctoolkit-result"
123126
a.postAnalysis = true
127+
a.Identifier = hpctoolkitIdentifier
124128

125129
// UseColor set to anything means to use it
126130
output, ok := metric.Options["output"]
@@ -399,7 +403,7 @@ sleep infinity
399403

400404
func init() {
401405
base := AddonBase{
402-
Identifier: "perf-hpctoolkit",
406+
Identifier: hpctoolkitIdentifier,
403407
Summary: "performance tools for measurement and analysis",
404408
}
405409
app := ApplicationAddon{AddonBase: base}

pkg/addons/volumes.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ import (
1919
"k8s.io/apimachinery/pkg/util/intstr"
2020
)
2121

22+
const (
23+
hostPathName = "volume-hostpath"
24+
pvcName = "volume-pvc"
25+
emptyName = "volume-empty"
26+
secretName = "volume-secret"
27+
cmName = "volume-cm"
28+
)
29+
2230
type VolumeBase struct {
2331
AddonBase
2432
readOnly bool
@@ -98,6 +106,8 @@ func (v *ConfigMapVolume) Validate() bool {
98106
// Set custom options / attributes for the metric
99107
func (v *ConfigMapVolume) SetOptions(metric *api.MetricAddon) {
100108

109+
v.Identifier = cmName
110+
101111
// Set an empty list of items
102112
v.items = map[string]string{}
103113

@@ -190,6 +200,9 @@ func (v *PersistentVolumeClaim) Validate() bool {
190200

191201
// Set custom options / attributes
192202
func (v *PersistentVolumeClaim) SetOptions(metric *api.MetricAddon) {
203+
204+
v.Identifier = pvcName
205+
193206
claimName, ok := metric.Options["claimName"]
194207
if ok {
195208
v.claimName = claimName.StrVal
@@ -207,8 +220,6 @@ func (v *PersistentVolumeClaim) AssembleVolumes() []specs.VolumeSpec {
207220
},
208221
},
209222
}
210-
211-
// ConfigMaps have to be read only!
212223
return []specs.VolumeSpec{{
213224
Volume: volume,
214225
Path: filepath.Dir(v.path),
@@ -236,6 +247,8 @@ func (v *SecretVolume) Validate() bool {
236247

237248
// Set custom options / attributes
238249
func (v *SecretVolume) SetOptions(metric *api.MetricAddon) {
250+
251+
v.Identifier = secretName
239252
secretName, ok := metric.Options["secretName"]
240253
if ok {
241254
v.secretName = secretName.StrVal
@@ -281,6 +294,8 @@ func (v *HostPathVolume) Validate() bool {
281294
// Set custom options / attributes
282295
func (v *HostPathVolume) SetOptions(metric *api.MetricAddon) {
283296

297+
v.Identifier = hostPathName
298+
284299
// Name is required!
285300
path, ok := metric.Options["hostPath"]
286301
if ok {
@@ -319,6 +334,7 @@ func (v *EmptyVolume) Validate() bool {
319334

320335
// Set custom options / attributes
321336
func (v *EmptyVolume) SetOptions(metric *api.MetricAddon) {
337+
v.Identifier = emptyName
322338
name, ok := metric.Options["name"]
323339
if ok {
324340
v.name = name.StrVal
@@ -347,7 +363,7 @@ func init() {
347363

348364
// Config map volume type
349365
base := AddonBase{
350-
Identifier: "volume-cm",
366+
Identifier: cmName,
351367
Summary: "config map volume type",
352368
}
353369
volBase := VolumeBase{AddonBase: base}
@@ -356,7 +372,7 @@ func init() {
356372

357373
// Secret volume type
358374
base = AddonBase{
359-
Identifier: "volume-secret",
375+
Identifier: secretName,
360376
Summary: "secret volume type",
361377
}
362378
volBase = VolumeBase{AddonBase: base}
@@ -365,7 +381,7 @@ func init() {
365381

366382
// Hostpath volume type
367383
base = AddonBase{
368-
Identifier: "volume-hostpath",
384+
Identifier: hostPathName,
369385
Summary: "host path volume type",
370386
}
371387
volBase = VolumeBase{AddonBase: base}
@@ -374,7 +390,7 @@ func init() {
374390

375391
// persistent volume claim volume type
376392
base = AddonBase{
377-
Identifier: "volume-pvc",
393+
Identifier: pvcName,
378394
Summary: "persistent volume claim volume type",
379395
}
380396
volBase = VolumeBase{AddonBase: base}
@@ -383,7 +399,7 @@ func init() {
383399

384400
// EmptyVolume
385401
base = AddonBase{
386-
Identifier: "volume-empty",
402+
Identifier: emptyName,
387403
Summary: "empty volume type",
388404
}
389405
volBase = VolumeBase{AddonBase: base}

pkg/metrics/base.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ type BaseMetric struct {
3939
func (m *BaseMetric) RegisterAddon(addon *addons.Addon) {
4040
a := (*addon)
4141
if m.Addons == nil {
42+
logger.Infof("🟧️ Resetting addons - they are unset.")
4243
m.Addons = map[string]*addons.Addon{}
4344
}
44-
logger.Infof("🟧️ Registering addon %s", a)
45+
logger.Infof("🟧️ Registering addon %s", a.Name())
4546
m.Addons[a.Name()] = addon
4647
}
4748

@@ -142,10 +143,10 @@ func (m BaseMetric) AddAddons(
142143
// These are container specs that need to be written to configmaps
143144
cms := []*specs.ContainerSpec{}
144145

145-
logger.Infof("🟧️ Addons to include %s\n", m.Addons)
146146
for _, addon := range m.Addons {
147147
a := (*addon)
148148

149+
logger.Infof("🟧️ Including Addon", a.Name())
149150
volumes = append(volumes, a.AssembleVolumes()...)
150151

151152
// Assemble containers that addons provide, also as specs

pkg/metrics/metrics.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ func GetMetric(metric *api.Metric, set *api.MetricSet) (Metric, error) {
8585
// Register addons, meaning adding the spec but not instantiating yet (or should we?)
8686
for _, a := range metric.Addons {
8787

88+
logger.Infof("Attempting to add addon %s", a.Name)
8889
addon, err := addons.GetAddon(&a)
8990
if err != nil {
9091
return nil, fmt.Errorf("Addon %s for metric %s did not validate", a.Name, metric.Name)
9192
}
93+
logger.Infof("Registering addon %s", a.Name)
9294
m.RegisterAddon(&addon)
9395
}
9496

0 commit comments

Comments
 (0)