1package device
2
3import (
4	"github.com/golang/protobuf/ptypes"
5	"github.com/hashicorp/nomad/plugins/device/proto"
6	"github.com/hashicorp/nomad/plugins/shared/structs"
7)
8
9// convertProtoDeviceGroups converts between a list of proto and structs DeviceGroup
10func convertProtoDeviceGroups(in []*proto.DeviceGroup) []*DeviceGroup {
11	if in == nil {
12		return nil
13	}
14
15	out := make([]*DeviceGroup, len(in))
16	for i, group := range in {
17		out[i] = convertProtoDeviceGroup(group)
18	}
19
20	return out
21}
22
23// convertProtoDeviceGroup converts between a proto and structs DeviceGroup
24func convertProtoDeviceGroup(in *proto.DeviceGroup) *DeviceGroup {
25	if in == nil {
26		return nil
27	}
28
29	return &DeviceGroup{
30		Vendor:     in.Vendor,
31		Type:       in.DeviceType,
32		Name:       in.DeviceName,
33		Devices:    convertProtoDevices(in.Devices),
34		Attributes: structs.ConvertProtoAttributeMap(in.Attributes),
35	}
36}
37
38// convertProtoDevices converts between a list of proto and structs Device
39func convertProtoDevices(in []*proto.DetectedDevice) []*Device {
40	if in == nil {
41		return nil
42	}
43
44	out := make([]*Device, len(in))
45	for i, d := range in {
46		out[i] = convertProtoDevice(d)
47	}
48
49	return out
50}
51
52// convertProtoDevice converts between a proto and structs Device
53func convertProtoDevice(in *proto.DetectedDevice) *Device {
54	if in == nil {
55		return nil
56	}
57
58	return &Device{
59		ID:         in.ID,
60		Healthy:    in.Healthy,
61		HealthDesc: in.HealthDescription,
62		HwLocality: convertProtoDeviceLocality(in.HwLocality),
63	}
64}
65
66// convertProtoDeviceLocality converts between a proto and structs DeviceLocality
67func convertProtoDeviceLocality(in *proto.DeviceLocality) *DeviceLocality {
68	if in == nil {
69		return nil
70	}
71
72	return &DeviceLocality{
73		PciBusID: in.PciBusId,
74	}
75}
76
77// convertProtoContainerReservation is used to convert between a proto and struct
78// ContainerReservation
79func convertProtoContainerReservation(in *proto.ContainerReservation) *ContainerReservation {
80	if in == nil {
81		return nil
82	}
83
84	return &ContainerReservation{
85		Envs:    in.Envs,
86		Mounts:  convertProtoMounts(in.Mounts),
87		Devices: convertProtoDeviceSpecs(in.Devices),
88	}
89}
90
91// convertProtoMount converts between a list of proto and structs Mount
92func convertProtoMounts(in []*proto.Mount) []*Mount {
93	if in == nil {
94		return nil
95	}
96
97	out := make([]*Mount, len(in))
98	for i, d := range in {
99		out[i] = convertProtoMount(d)
100	}
101
102	return out
103}
104
105// convertProtoMount converts between a proto and structs Mount
106func convertProtoMount(in *proto.Mount) *Mount {
107	if in == nil {
108		return nil
109	}
110
111	return &Mount{
112		TaskPath: in.TaskPath,
113		HostPath: in.HostPath,
114		ReadOnly: in.ReadOnly,
115	}
116}
117
118// convertProtoDeviceSpecs converts between a list of proto and structs DeviceSpecs
119func convertProtoDeviceSpecs(in []*proto.DeviceSpec) []*DeviceSpec {
120	if in == nil {
121		return nil
122	}
123
124	out := make([]*DeviceSpec, len(in))
125	for i, d := range in {
126		out[i] = convertProtoDeviceSpec(d)
127	}
128
129	return out
130}
131
132// convertProtoDeviceSpec converts between a proto and structs DeviceSpec
133func convertProtoDeviceSpec(in *proto.DeviceSpec) *DeviceSpec {
134	if in == nil {
135		return nil
136	}
137
138	return &DeviceSpec{
139		TaskPath:    in.TaskPath,
140		HostPath:    in.HostPath,
141		CgroupPerms: in.Permissions,
142	}
143}
144
145// convertStructDeviceGroup converts between a list of struct and proto DeviceGroup
146func convertStructDeviceGroups(in []*DeviceGroup) []*proto.DeviceGroup {
147	if in == nil {
148		return nil
149	}
150
151	out := make([]*proto.DeviceGroup, len(in))
152	for i, g := range in {
153		out[i] = convertStructDeviceGroup(g)
154	}
155
156	return out
157}
158
159// convertStructDeviceGroup converts between a struct and proto DeviceGroup
160func convertStructDeviceGroup(in *DeviceGroup) *proto.DeviceGroup {
161	if in == nil {
162		return nil
163	}
164
165	return &proto.DeviceGroup{
166		Vendor:     in.Vendor,
167		DeviceType: in.Type,
168		DeviceName: in.Name,
169		Devices:    convertStructDevices(in.Devices),
170		Attributes: structs.ConvertStructAttributeMap(in.Attributes),
171	}
172}
173
174// convertStructDevices converts between a list of struct and proto Device
175func convertStructDevices(in []*Device) []*proto.DetectedDevice {
176	if in == nil {
177		return nil
178	}
179
180	out := make([]*proto.DetectedDevice, len(in))
181	for i, d := range in {
182		out[i] = convertStructDevice(d)
183	}
184
185	return out
186}
187
188// convertStructDevice converts between a struct and proto Device
189func convertStructDevice(in *Device) *proto.DetectedDevice {
190	if in == nil {
191		return nil
192	}
193
194	return &proto.DetectedDevice{
195		ID:                in.ID,
196		Healthy:           in.Healthy,
197		HealthDescription: in.HealthDesc,
198		HwLocality:        convertStructDeviceLocality(in.HwLocality),
199	}
200}
201
202// convertStructDeviceLocality converts between a struct and proto DeviceLocality
203func convertStructDeviceLocality(in *DeviceLocality) *proto.DeviceLocality {
204	if in == nil {
205		return nil
206	}
207
208	return &proto.DeviceLocality{
209		PciBusId: in.PciBusID,
210	}
211}
212
213// convertStructContainerReservation is used to convert between a struct and
214// proto ContainerReservation
215func convertStructContainerReservation(in *ContainerReservation) *proto.ContainerReservation {
216	if in == nil {
217		return nil
218	}
219
220	return &proto.ContainerReservation{
221		Envs:    in.Envs,
222		Mounts:  convertStructMounts(in.Mounts),
223		Devices: convertStructDeviceSpecs(in.Devices),
224	}
225}
226
227// convertStructMount converts between a list of structs and proto Mount
228func convertStructMounts(in []*Mount) []*proto.Mount {
229	if in == nil {
230		return nil
231	}
232
233	out := make([]*proto.Mount, len(in))
234	for i, m := range in {
235		out[i] = convertStructMount(m)
236	}
237
238	return out
239}
240
241// convertStructMount converts between a struct and proto Mount
242func convertStructMount(in *Mount) *proto.Mount {
243	if in == nil {
244		return nil
245	}
246
247	return &proto.Mount{
248		TaskPath: in.TaskPath,
249		HostPath: in.HostPath,
250		ReadOnly: in.ReadOnly,
251	}
252}
253
254// convertStructDeviceSpecs converts between a list of struct and proto DeviceSpecs
255func convertStructDeviceSpecs(in []*DeviceSpec) []*proto.DeviceSpec {
256	if in == nil {
257		return nil
258	}
259
260	out := make([]*proto.DeviceSpec, len(in))
261	for i, d := range in {
262		out[i] = convertStructDeviceSpec(d)
263	}
264
265	return out
266}
267
268// convertStructDeviceSpec converts between a struct and proto DeviceSpec
269func convertStructDeviceSpec(in *DeviceSpec) *proto.DeviceSpec {
270	if in == nil {
271		return nil
272	}
273
274	return &proto.DeviceSpec{
275		TaskPath:    in.TaskPath,
276		HostPath:    in.HostPath,
277		Permissions: in.CgroupPerms,
278	}
279}
280
281// convertProtoDeviceGroupsStats converts between a list of struct and proto
282// DeviceGroupStats
283func convertProtoDeviceGroupsStats(in []*proto.DeviceGroupStats) []*DeviceGroupStats {
284	if in == nil {
285		return nil
286	}
287
288	out := make([]*DeviceGroupStats, len(in))
289	for i, m := range in {
290		out[i] = convertProtoDeviceGroupStats(m)
291	}
292
293	return out
294}
295
296// convertProtoDeviceGroupStats converts between a proto and struct
297// DeviceGroupStats
298func convertProtoDeviceGroupStats(in *proto.DeviceGroupStats) *DeviceGroupStats {
299	if in == nil {
300		return nil
301	}
302
303	out := &DeviceGroupStats{
304		Vendor:        in.Vendor,
305		Type:          in.Type,
306		Name:          in.Name,
307		InstanceStats: make(map[string]*DeviceStats, len(in.InstanceStats)),
308	}
309
310	for k, v := range in.InstanceStats {
311		out.InstanceStats[k] = convertProtoDeviceStats(v)
312	}
313
314	return out
315}
316
317// convertProtoDeviceStats converts between a proto and struct DeviceStats
318func convertProtoDeviceStats(in *proto.DeviceStats) *DeviceStats {
319	if in == nil {
320		return nil
321	}
322
323	ts, err := ptypes.Timestamp(in.Timestamp)
324	if err != nil {
325		return nil
326	}
327
328	return &DeviceStats{
329		Summary:   structs.ConvertProtoStatValue(in.Summary),
330		Stats:     structs.ConvertProtoStatObject(in.Stats),
331		Timestamp: ts,
332	}
333}
334
335// convertStructDeviceGroupsStats converts between a list of struct and proto
336// DeviceGroupStats
337func convertStructDeviceGroupsStats(in []*DeviceGroupStats) []*proto.DeviceGroupStats {
338	if in == nil {
339		return nil
340	}
341
342	out := make([]*proto.DeviceGroupStats, len(in))
343	for i, m := range in {
344		out[i] = convertStructDeviceGroupStats(m)
345	}
346
347	return out
348}
349
350// convertStructDeviceGroupStats converts between a struct and proto
351// DeviceGroupStats
352func convertStructDeviceGroupStats(in *DeviceGroupStats) *proto.DeviceGroupStats {
353	if in == nil {
354		return nil
355	}
356
357	out := &proto.DeviceGroupStats{
358		Vendor:        in.Vendor,
359		Type:          in.Type,
360		Name:          in.Name,
361		InstanceStats: make(map[string]*proto.DeviceStats, len(in.InstanceStats)),
362	}
363
364	for k, v := range in.InstanceStats {
365		out.InstanceStats[k] = convertStructDeviceStats(v)
366	}
367
368	return out
369}
370
371// convertStructDeviceStats converts between a struct and proto DeviceStats
372func convertStructDeviceStats(in *DeviceStats) *proto.DeviceStats {
373	if in == nil {
374		return nil
375	}
376
377	ts, err := ptypes.TimestampProto(in.Timestamp)
378	if err != nil {
379		return nil
380	}
381
382	return &proto.DeviceStats{
383		Summary:   structs.ConvertStructStatValue(in.Summary),
384		Stats:     structs.ConvertStructStatObject(in.Stats),
385		Timestamp: ts,
386	}
387}
388