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