1package api
2
3import (
4	"strconv"
5)
6
7// Resources encapsulates the required resources of
8// a given task or task group.
9type Resources struct {
10	CPU      *int
11	MemoryMB *int `mapstructure:"memory"`
12	DiskMB   *int `mapstructure:"disk"`
13	Networks []*NetworkResource
14	Devices  []*RequestedDevice
15
16	// COMPAT(0.10)
17	// XXX Deprecated. Please do not use. The field will be removed in Nomad
18	// 0.10 and is only being kept to allow any references to be removed before
19	// then.
20	IOPS *int
21}
22
23// Canonicalize will supply missing values in the cases
24// where they are not provided.
25func (r *Resources) Canonicalize() {
26	defaultResources := DefaultResources()
27	if r.CPU == nil {
28		r.CPU = defaultResources.CPU
29	}
30	if r.MemoryMB == nil {
31		r.MemoryMB = defaultResources.MemoryMB
32	}
33	for _, n := range r.Networks {
34		n.Canonicalize()
35	}
36	for _, d := range r.Devices {
37		d.Canonicalize()
38	}
39}
40
41// DefaultResources is a small resources object that contains the
42// default resources requests that we will provide to an object.
43// ---  THIS FUNCTION IS REPLICATED IN nomad/structs/structs.go
44// and should be kept in sync.
45func DefaultResources() *Resources {
46	return &Resources{
47		CPU:      intToPtr(100),
48		MemoryMB: intToPtr(300),
49	}
50}
51
52// MinResources is a small resources object that contains the
53// absolute minimum resources that we will provide to an object.
54// This should not be confused with the defaults which are
55// provided in DefaultResources() ---  THIS LOGIC IS REPLICATED
56// IN nomad/structs/structs.go and should be kept in sync.
57func MinResources() *Resources {
58	return &Resources{
59		CPU:      intToPtr(20),
60		MemoryMB: intToPtr(10),
61	}
62}
63
64// Merge merges this resource with another resource.
65func (r *Resources) Merge(other *Resources) {
66	if other == nil {
67		return
68	}
69	if other.CPU != nil {
70		r.CPU = other.CPU
71	}
72	if other.MemoryMB != nil {
73		r.MemoryMB = other.MemoryMB
74	}
75	if other.DiskMB != nil {
76		r.DiskMB = other.DiskMB
77	}
78	if len(other.Networks) != 0 {
79		r.Networks = other.Networks
80	}
81	if len(other.Devices) != 0 {
82		r.Devices = other.Devices
83	}
84}
85
86type Port struct {
87	Label string
88	Value int `mapstructure:"static"`
89}
90
91// NetworkResource is used to describe required network
92// resources of a given task.
93type NetworkResource struct {
94	Device        string
95	CIDR          string
96	IP            string
97	MBits         *int
98	ReservedPorts []Port
99	DynamicPorts  []Port
100}
101
102func (n *NetworkResource) Canonicalize() {
103	if n.MBits == nil {
104		n.MBits = intToPtr(10)
105	}
106}
107
108// NodeDeviceResource captures a set of devices sharing a common
109// vendor/type/device_name tuple.
110type NodeDeviceResource struct {
111
112	// Vendor specifies the vendor of device
113	Vendor string
114
115	// Type specifies the type of the device
116	Type string
117
118	// Name specifies the specific model of the device
119	Name string
120
121	// Instances are list of the devices matching the vendor/type/name
122	Instances []*NodeDevice
123
124	Attributes map[string]*Attribute
125}
126
127func (r NodeDeviceResource) ID() string {
128	return r.Vendor + "/" + r.Type + "/" + r.Name
129}
130
131// NodeDevice is an instance of a particular device.
132type NodeDevice struct {
133	// ID is the ID of the device.
134	ID string
135
136	// Healthy captures whether the device is healthy.
137	Healthy bool
138
139	// HealthDescription is used to provide a human readable description of why
140	// the device may be unhealthy.
141	HealthDescription string
142
143	// Locality stores HW locality information for the node to optionally be
144	// used when making placement decisions.
145	Locality *NodeDeviceLocality
146}
147
148// Attribute is used to describe the value of an attribute, optionally
149// specifying units
150type Attribute struct {
151	// Float is the float value for the attribute
152	FloatVal *float64 `json:"Float,omitempty"`
153
154	// Int is the int value for the attribute
155	IntVal *int64 `json:"Int,omitempty"`
156
157	// String is the string value for the attribute
158	StringVal *string `json:"String,omitempty"`
159
160	// Bool is the bool value for the attribute
161	BoolVal *bool `json:"Bool,omitempty"`
162
163	// Unit is the optional unit for the set int or float value
164	Unit string
165}
166
167func (a Attribute) String() string {
168	switch {
169	case a.FloatVal != nil:
170		str := formatFloat(*a.FloatVal, 3)
171		if a.Unit != "" {
172			str += " " + a.Unit
173		}
174		return str
175	case a.IntVal != nil:
176		str := strconv.FormatInt(*a.IntVal, 10)
177		if a.Unit != "" {
178			str += " " + a.Unit
179		}
180		return str
181	case a.StringVal != nil:
182		return *a.StringVal
183	case a.BoolVal != nil:
184		return strconv.FormatBool(*a.BoolVal)
185	default:
186		return "<unknown>"
187	}
188}
189
190// NodeDeviceLocality stores information about the devices hardware locality on
191// the node.
192type NodeDeviceLocality struct {
193	// PciBusID is the PCI Bus ID for the device.
194	PciBusID string
195}
196
197// RequestedDevice is used to request a device for a task.
198type RequestedDevice struct {
199	// Name is the request name. The possible values are as follows:
200	// * <type>: A single value only specifies the type of request.
201	// * <vendor>/<type>: A single slash delimiter assumes the vendor and type of device is specified.
202	// * <vendor>/<type>/<name>: Two slash delimiters assume vendor, type and specific model are specified.
203	//
204	// Examples are as follows:
205	// * "gpu"
206	// * "nvidia/gpu"
207	// * "nvidia/gpu/GTX2080Ti"
208	Name string
209
210	// Count is the number of requested devices
211	Count *uint64
212
213	// Constraints are a set of constraints to apply when selecting the device
214	// to use.
215	Constraints []*Constraint
216
217	// Affinities are a set of affinites to apply when selecting the device
218	// to use.
219	Affinities []*Affinity
220}
221
222func (d *RequestedDevice) Canonicalize() {
223	if d.Count == nil {
224		d.Count = uint64ToPtr(1)
225	}
226
227	for _, a := range d.Affinities {
228		a.Canonicalize()
229	}
230}
231