github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/plugins/drivers/utils.go (about) 1 package drivers 2 3 import ( 4 "time" 5 6 "github.com/golang/protobuf/ptypes" 7 "github.com/hashicorp/nomad/nomad/structs" 8 "github.com/hashicorp/nomad/plugins/drivers/proto" 9 ) 10 11 var taskStateToProtoMap = map[TaskState]proto.TaskState{ 12 TaskStateUnknown: proto.TaskState_UNKNOWN, 13 TaskStateRunning: proto.TaskState_RUNNING, 14 TaskStateExited: proto.TaskState_EXITED, 15 } 16 17 var taskStateFromProtoMap = map[proto.TaskState]TaskState{ 18 proto.TaskState_UNKNOWN: TaskStateUnknown, 19 proto.TaskState_RUNNING: TaskStateRunning, 20 proto.TaskState_EXITED: TaskStateExited, 21 } 22 23 func healthStateToProto(health HealthState) proto.FingerprintResponse_HealthState { 24 switch health { 25 case HealthStateUndetected: 26 return proto.FingerprintResponse_UNDETECTED 27 case HealthStateUnhealthy: 28 return proto.FingerprintResponse_UNHEALTHY 29 case HealthStateHealthy: 30 return proto.FingerprintResponse_HEALTHY 31 } 32 return proto.FingerprintResponse_UNDETECTED 33 } 34 35 func healthStateFromProto(pb proto.FingerprintResponse_HealthState) HealthState { 36 switch pb { 37 case proto.FingerprintResponse_UNDETECTED: 38 return HealthStateUndetected 39 case proto.FingerprintResponse_UNHEALTHY: 40 return HealthStateUnhealthy 41 case proto.FingerprintResponse_HEALTHY: 42 return HealthStateHealthy 43 } 44 return HealthStateUndetected 45 } 46 47 func taskConfigFromProto(pb *proto.TaskConfig) *TaskConfig { 48 if pb == nil { 49 return &TaskConfig{} 50 } 51 return &TaskConfig{ 52 ID: pb.Id, 53 JobName: pb.JobName, 54 TaskGroupName: pb.TaskGroupName, 55 Name: pb.Name, 56 Env: pb.Env, 57 DeviceEnv: pb.DeviceEnv, 58 rawDriverConfig: pb.MsgpackDriverConfig, 59 Resources: ResourcesFromProto(pb.Resources), 60 Devices: DevicesFromProto(pb.Devices), 61 Mounts: MountsFromProto(pb.Mounts), 62 User: pb.User, 63 AllocDir: pb.AllocDir, 64 StdoutPath: pb.StdoutPath, 65 StderrPath: pb.StderrPath, 66 AllocID: pb.AllocId, 67 NetworkIsolation: NetworkIsolationSpecFromProto(pb.NetworkIsolationSpec), 68 DNS: dnsConfigFromProto(pb.Dns), 69 } 70 } 71 72 func taskConfigToProto(cfg *TaskConfig) *proto.TaskConfig { 73 if cfg == nil { 74 return &proto.TaskConfig{} 75 } 76 pb := &proto.TaskConfig{ 77 Id: cfg.ID, 78 JobName: cfg.JobName, 79 TaskGroupName: cfg.TaskGroupName, 80 Name: cfg.Name, 81 Env: cfg.Env, 82 DeviceEnv: cfg.DeviceEnv, 83 Resources: ResourcesToProto(cfg.Resources), 84 Devices: DevicesToProto(cfg.Devices), 85 Mounts: MountsToProto(cfg.Mounts), 86 User: cfg.User, 87 AllocDir: cfg.AllocDir, 88 MsgpackDriverConfig: cfg.rawDriverConfig, 89 StdoutPath: cfg.StdoutPath, 90 StderrPath: cfg.StderrPath, 91 AllocId: cfg.AllocID, 92 NetworkIsolationSpec: NetworkIsolationSpecToProto(cfg.NetworkIsolation), 93 Dns: dnsConfigToProto(cfg.DNS), 94 } 95 return pb 96 } 97 98 func ResourcesFromProto(pb *proto.Resources) *Resources { 99 var r Resources 100 if pb == nil { 101 return &r 102 } 103 104 if pb.AllocatedResources != nil { 105 r.NomadResources = &structs.AllocatedTaskResources{} 106 107 if pb.AllocatedResources.Cpu != nil { 108 r.NomadResources.Cpu.CpuShares = pb.AllocatedResources.Cpu.CpuShares 109 } 110 111 if pb.AllocatedResources.Memory != nil { 112 r.NomadResources.Memory.MemoryMB = pb.AllocatedResources.Memory.MemoryMb 113 } 114 115 for _, network := range pb.AllocatedResources.Networks { 116 var n structs.NetworkResource 117 n.Device = network.Device 118 n.IP = network.Ip 119 n.CIDR = network.Cidr 120 n.MBits = int(network.Mbits) 121 for _, port := range network.ReservedPorts { 122 n.ReservedPorts = append(n.ReservedPorts, structs.Port{ 123 Label: port.Label, 124 Value: int(port.Value), 125 }) 126 } 127 for _, port := range network.DynamicPorts { 128 n.DynamicPorts = append(n.DynamicPorts, structs.Port{ 129 Label: port.Label, 130 Value: int(port.Value), 131 }) 132 } 133 r.NomadResources.Networks = append(r.NomadResources.Networks, &n) 134 } 135 } 136 137 if pb.LinuxResources != nil { 138 r.LinuxResources = &LinuxResources{ 139 CPUPeriod: pb.LinuxResources.CpuPeriod, 140 CPUQuota: pb.LinuxResources.CpuQuota, 141 CPUShares: pb.LinuxResources.CpuShares, 142 MemoryLimitBytes: pb.LinuxResources.MemoryLimitBytes, 143 OOMScoreAdj: pb.LinuxResources.OomScoreAdj, 144 CpusetCPUs: pb.LinuxResources.CpusetCpus, 145 CpusetMems: pb.LinuxResources.CpusetMems, 146 PercentTicks: pb.LinuxResources.PercentTicks, 147 } 148 } 149 150 if pb.Ports != nil { 151 ports := structs.AllocatedPorts(make([]structs.AllocatedPortMapping, len(pb.Ports))) 152 for i, port := range pb.Ports { 153 ports[i] = structs.AllocatedPortMapping{ 154 Label: port.Label, 155 Value: int(port.Value), 156 To: int(port.To), 157 HostIP: port.HostIp, 158 } 159 } 160 r.Ports = &ports 161 } 162 163 return &r 164 } 165 166 func ResourcesToProto(r *Resources) *proto.Resources { 167 if r == nil { 168 return nil 169 } 170 171 var pb proto.Resources 172 if r.NomadResources != nil { 173 pb.AllocatedResources = &proto.AllocatedTaskResources{ 174 Cpu: &proto.AllocatedCpuResources{ 175 CpuShares: r.NomadResources.Cpu.CpuShares, 176 }, 177 Memory: &proto.AllocatedMemoryResources{ 178 MemoryMb: r.NomadResources.Memory.MemoryMB, 179 }, 180 Networks: make([]*proto.NetworkResource, len(r.NomadResources.Networks)), 181 } 182 183 for i, network := range r.NomadResources.Networks { 184 var n proto.NetworkResource 185 n.Device = network.Device 186 n.Ip = network.IP 187 n.Cidr = network.CIDR 188 n.Mbits = int32(network.MBits) 189 n.ReservedPorts = []*proto.NetworkPort{} 190 for _, port := range network.ReservedPorts { 191 n.ReservedPorts = append(n.ReservedPorts, &proto.NetworkPort{ 192 Label: port.Label, 193 Value: int32(port.Value), 194 }) 195 } 196 for _, port := range network.DynamicPorts { 197 n.DynamicPorts = append(n.DynamicPorts, &proto.NetworkPort{ 198 Label: port.Label, 199 Value: int32(port.Value), 200 }) 201 } 202 pb.AllocatedResources.Networks[i] = &n 203 } 204 } 205 206 if r.LinuxResources != nil { 207 pb.LinuxResources = &proto.LinuxResources{ 208 CpuPeriod: r.LinuxResources.CPUPeriod, 209 CpuQuota: r.LinuxResources.CPUQuota, 210 CpuShares: r.LinuxResources.CPUShares, 211 MemoryLimitBytes: r.LinuxResources.MemoryLimitBytes, 212 OomScoreAdj: r.LinuxResources.OOMScoreAdj, 213 CpusetCpus: r.LinuxResources.CpusetCPUs, 214 CpusetMems: r.LinuxResources.CpusetMems, 215 PercentTicks: r.LinuxResources.PercentTicks, 216 } 217 } 218 219 if r.Ports != nil { 220 ports := make([]*proto.PortMapping, len(*r.Ports)) 221 for i, port := range *r.Ports { 222 ports[i] = &proto.PortMapping{ 223 Label: port.Label, 224 Value: int32(port.Value), 225 To: int32(port.To), 226 HostIp: port.HostIP, 227 } 228 } 229 230 pb.Ports = ports 231 } 232 233 return &pb 234 } 235 236 func DevicesFromProto(devices []*proto.Device) []*DeviceConfig { 237 if devices == nil { 238 return nil 239 } 240 241 out := make([]*DeviceConfig, len(devices)) 242 for i, d := range devices { 243 out[i] = DeviceFromProto(d) 244 } 245 246 return out 247 } 248 249 func DeviceFromProto(device *proto.Device) *DeviceConfig { 250 if device == nil { 251 return nil 252 } 253 254 return &DeviceConfig{ 255 TaskPath: device.TaskPath, 256 HostPath: device.HostPath, 257 Permissions: device.CgroupPermissions, 258 } 259 } 260 261 func MountsFromProto(mounts []*proto.Mount) []*MountConfig { 262 if mounts == nil { 263 return nil 264 } 265 266 out := make([]*MountConfig, len(mounts)) 267 for i, m := range mounts { 268 out[i] = MountFromProto(m) 269 } 270 271 return out 272 } 273 274 func MountFromProto(mount *proto.Mount) *MountConfig { 275 if mount == nil { 276 return nil 277 } 278 279 return &MountConfig{ 280 TaskPath: mount.TaskPath, 281 HostPath: mount.HostPath, 282 Readonly: mount.Readonly, 283 } 284 } 285 286 func DevicesToProto(devices []*DeviceConfig) []*proto.Device { 287 if devices == nil { 288 return nil 289 } 290 291 out := make([]*proto.Device, len(devices)) 292 for i, d := range devices { 293 out[i] = DeviceToProto(d) 294 } 295 296 return out 297 } 298 299 func DeviceToProto(device *DeviceConfig) *proto.Device { 300 if device == nil { 301 return nil 302 } 303 304 return &proto.Device{ 305 TaskPath: device.TaskPath, 306 HostPath: device.HostPath, 307 CgroupPermissions: device.Permissions, 308 } 309 } 310 311 func MountsToProto(mounts []*MountConfig) []*proto.Mount { 312 if mounts == nil { 313 return nil 314 } 315 316 out := make([]*proto.Mount, len(mounts)) 317 for i, m := range mounts { 318 out[i] = MountToProto(m) 319 } 320 321 return out 322 } 323 324 func MountToProto(mount *MountConfig) *proto.Mount { 325 if mount == nil { 326 return nil 327 } 328 329 return &proto.Mount{ 330 TaskPath: mount.TaskPath, 331 HostPath: mount.HostPath, 332 Readonly: mount.Readonly, 333 } 334 } 335 336 func taskHandleFromProto(pb *proto.TaskHandle) *TaskHandle { 337 if pb == nil { 338 return &TaskHandle{} 339 } 340 return &TaskHandle{ 341 Version: int(pb.Version), 342 Config: taskConfigFromProto(pb.Config), 343 State: taskStateFromProtoMap[pb.State], 344 DriverState: pb.DriverState, 345 } 346 } 347 348 func taskHandleToProto(handle *TaskHandle) *proto.TaskHandle { 349 return &proto.TaskHandle{ 350 Version: int32(handle.Version), 351 Config: taskConfigToProto(handle.Config), 352 State: taskStateToProtoMap[handle.State], 353 DriverState: handle.DriverState, 354 } 355 } 356 357 func exitResultToProto(result *ExitResult) *proto.ExitResult { 358 if result == nil { 359 return &proto.ExitResult{} 360 } 361 return &proto.ExitResult{ 362 ExitCode: int32(result.ExitCode), 363 Signal: int32(result.Signal), 364 OomKilled: result.OOMKilled, 365 } 366 } 367 368 func exitResultFromProto(pb *proto.ExitResult) *ExitResult { 369 return &ExitResult{ 370 ExitCode: int(pb.ExitCode), 371 Signal: int(pb.Signal), 372 OOMKilled: pb.OomKilled, 373 } 374 } 375 376 func taskStatusToProto(status *TaskStatus) (*proto.TaskStatus, error) { 377 started, err := ptypes.TimestampProto(status.StartedAt) 378 if err != nil { 379 return nil, err 380 } 381 completed, err := ptypes.TimestampProto(status.CompletedAt) 382 if err != nil { 383 return nil, err 384 } 385 return &proto.TaskStatus{ 386 Id: status.ID, 387 Name: status.Name, 388 State: taskStateToProtoMap[status.State], 389 StartedAt: started, 390 CompletedAt: completed, 391 Result: exitResultToProto(status.ExitResult), 392 }, nil 393 } 394 395 func taskStatusFromProto(pb *proto.TaskStatus) (*TaskStatus, error) { 396 started, err := ptypes.Timestamp(pb.StartedAt) 397 if err != nil { 398 return nil, err 399 } 400 401 completed, err := ptypes.Timestamp(pb.CompletedAt) 402 if err != nil { 403 return nil, err 404 } 405 406 return &TaskStatus{ 407 ID: pb.Id, 408 Name: pb.Name, 409 State: taskStateFromProtoMap[pb.State], 410 StartedAt: started, 411 CompletedAt: completed, 412 ExitResult: exitResultFromProto(pb.Result), 413 }, nil 414 } 415 416 func TaskStatsToProto(stats *TaskResourceUsage) (*proto.TaskStats, error) { 417 timestamp, err := ptypes.TimestampProto(time.Unix(0, stats.Timestamp)) 418 if err != nil { 419 return nil, err 420 } 421 422 pids := map[string]*proto.TaskResourceUsage{} 423 for pid, ru := range stats.Pids { 424 pids[pid] = resourceUsageToProto(ru) 425 } 426 427 return &proto.TaskStats{ 428 Timestamp: timestamp, 429 AggResourceUsage: resourceUsageToProto(stats.ResourceUsage), 430 ResourceUsageByPid: pids, 431 }, nil 432 } 433 434 func TaskStatsFromProto(pb *proto.TaskStats) (*TaskResourceUsage, error) { 435 timestamp, err := ptypes.Timestamp(pb.Timestamp) 436 if err != nil { 437 return nil, err 438 } 439 440 pids := map[string]*ResourceUsage{} 441 for pid, ru := range pb.ResourceUsageByPid { 442 pids[pid] = resourceUsageFromProto(ru) 443 } 444 445 stats := &TaskResourceUsage{ 446 Timestamp: timestamp.UnixNano(), 447 ResourceUsage: resourceUsageFromProto(pb.AggResourceUsage), 448 Pids: pids, 449 } 450 451 return stats, nil 452 } 453 454 func resourceUsageToProto(ru *ResourceUsage) *proto.TaskResourceUsage { 455 cpu := &proto.CPUUsage{ 456 MeasuredFields: cpuUsageMeasuredFieldsToProto(ru.CpuStats.Measured), 457 SystemMode: ru.CpuStats.SystemMode, 458 UserMode: ru.CpuStats.UserMode, 459 TotalTicks: ru.CpuStats.TotalTicks, 460 ThrottledPeriods: ru.CpuStats.ThrottledPeriods, 461 ThrottledTime: ru.CpuStats.ThrottledTime, 462 Percent: ru.CpuStats.Percent, 463 } 464 465 memory := &proto.MemoryUsage{ 466 MeasuredFields: memoryUsageMeasuredFieldsToProto(ru.MemoryStats.Measured), 467 Rss: ru.MemoryStats.RSS, 468 Cache: ru.MemoryStats.Cache, 469 Swap: ru.MemoryStats.Swap, 470 Usage: ru.MemoryStats.Usage, 471 MaxUsage: ru.MemoryStats.MaxUsage, 472 KernelUsage: ru.MemoryStats.KernelUsage, 473 KernelMaxUsage: ru.MemoryStats.KernelMaxUsage, 474 } 475 476 return &proto.TaskResourceUsage{ 477 Cpu: cpu, 478 Memory: memory, 479 } 480 } 481 482 func resourceUsageFromProto(pb *proto.TaskResourceUsage) *ResourceUsage { 483 cpu := CpuStats{} 484 if pb.Cpu != nil { 485 cpu = CpuStats{ 486 Measured: cpuUsageMeasuredFieldsFromProto(pb.Cpu.MeasuredFields), 487 SystemMode: pb.Cpu.SystemMode, 488 UserMode: pb.Cpu.UserMode, 489 TotalTicks: pb.Cpu.TotalTicks, 490 ThrottledPeriods: pb.Cpu.ThrottledPeriods, 491 ThrottledTime: pb.Cpu.ThrottledTime, 492 Percent: pb.Cpu.Percent, 493 } 494 } 495 496 memory := MemoryStats{} 497 if pb.Memory != nil { 498 memory = MemoryStats{ 499 Measured: memoryUsageMeasuredFieldsFromProto(pb.Memory.MeasuredFields), 500 RSS: pb.Memory.Rss, 501 Cache: pb.Memory.Cache, 502 Swap: pb.Memory.Swap, 503 Usage: pb.Memory.Usage, 504 MaxUsage: pb.Memory.MaxUsage, 505 KernelUsage: pb.Memory.KernelUsage, 506 KernelMaxUsage: pb.Memory.KernelMaxUsage, 507 } 508 } 509 510 return &ResourceUsage{ 511 CpuStats: &cpu, 512 MemoryStats: &memory, 513 } 514 } 515 516 func BytesToMB(bytes int64) int64 { 517 return bytes / (1024 * 1024) 518 } 519 520 var cpuUsageMeasuredFieldToProtoMap = map[string]proto.CPUUsage_Fields{ 521 "System Mode": proto.CPUUsage_SYSTEM_MODE, 522 "User Mode": proto.CPUUsage_USER_MODE, 523 "Total Ticks": proto.CPUUsage_TOTAL_TICKS, 524 "Throttled Periods": proto.CPUUsage_THROTTLED_PERIODS, 525 "Throttled Time": proto.CPUUsage_THROTTLED_TIME, 526 "Percent": proto.CPUUsage_PERCENT, 527 } 528 529 var cpuUsageMeasuredFieldFromProtoMap = map[proto.CPUUsage_Fields]string{ 530 proto.CPUUsage_SYSTEM_MODE: "System Mode", 531 proto.CPUUsage_USER_MODE: "User Mode", 532 proto.CPUUsage_TOTAL_TICKS: "Total Ticks", 533 proto.CPUUsage_THROTTLED_PERIODS: "Throttled Periods", 534 proto.CPUUsage_THROTTLED_TIME: "Throttled Time", 535 proto.CPUUsage_PERCENT: "Percent", 536 } 537 538 func cpuUsageMeasuredFieldsToProto(fields []string) []proto.CPUUsage_Fields { 539 r := make([]proto.CPUUsage_Fields, 0, len(fields)) 540 541 for _, f := range fields { 542 if v, ok := cpuUsageMeasuredFieldToProtoMap[f]; ok { 543 r = append(r, v) 544 } 545 } 546 547 return r 548 } 549 550 func cpuUsageMeasuredFieldsFromProto(fields []proto.CPUUsage_Fields) []string { 551 r := make([]string, 0, len(fields)) 552 553 for _, f := range fields { 554 if v, ok := cpuUsageMeasuredFieldFromProtoMap[f]; ok { 555 r = append(r, v) 556 } 557 } 558 559 return r 560 } 561 562 var memoryUsageMeasuredFieldToProtoMap = map[string]proto.MemoryUsage_Fields{ 563 "RSS": proto.MemoryUsage_RSS, 564 "Cache": proto.MemoryUsage_CACHE, 565 "Swap": proto.MemoryUsage_SWAP, 566 "Usage": proto.MemoryUsage_USAGE, 567 "Max Usage": proto.MemoryUsage_MAX_USAGE, 568 "Kernel Usage": proto.MemoryUsage_KERNEL_USAGE, 569 "Kernel Max Usage": proto.MemoryUsage_KERNEL_MAX_USAGE, 570 } 571 572 var memoryUsageMeasuredFieldFromProtoMap = map[proto.MemoryUsage_Fields]string{ 573 proto.MemoryUsage_RSS: "RSS", 574 proto.MemoryUsage_CACHE: "Cache", 575 proto.MemoryUsage_SWAP: "Swap", 576 proto.MemoryUsage_USAGE: "Usage", 577 proto.MemoryUsage_MAX_USAGE: "Max Usage", 578 proto.MemoryUsage_KERNEL_USAGE: "Kernel Usage", 579 proto.MemoryUsage_KERNEL_MAX_USAGE: "Kernel Max Usage", 580 } 581 582 func memoryUsageMeasuredFieldsToProto(fields []string) []proto.MemoryUsage_Fields { 583 r := make([]proto.MemoryUsage_Fields, 0, len(fields)) 584 585 for _, f := range fields { 586 if v, ok := memoryUsageMeasuredFieldToProtoMap[f]; ok { 587 r = append(r, v) 588 } 589 } 590 591 return r 592 } 593 594 func memoryUsageMeasuredFieldsFromProto(fields []proto.MemoryUsage_Fields) []string { 595 r := make([]string, 0, len(fields)) 596 597 for _, f := range fields { 598 if v, ok := memoryUsageMeasuredFieldFromProtoMap[f]; ok { 599 r = append(r, v) 600 } 601 } 602 603 return r 604 } 605 606 func netIsolationModeToProto(mode NetIsolationMode) proto.NetworkIsolationSpec_NetworkIsolationMode { 607 switch mode { 608 case NetIsolationModeHost: 609 return proto.NetworkIsolationSpec_HOST 610 case NetIsolationModeGroup: 611 return proto.NetworkIsolationSpec_GROUP 612 case NetIsolationModeTask: 613 return proto.NetworkIsolationSpec_TASK 614 case NetIsolationModeNone: 615 return proto.NetworkIsolationSpec_NONE 616 default: 617 return proto.NetworkIsolationSpec_HOST 618 } 619 } 620 621 func netIsolationModeFromProto(pb proto.NetworkIsolationSpec_NetworkIsolationMode) NetIsolationMode { 622 switch pb { 623 case proto.NetworkIsolationSpec_HOST: 624 return NetIsolationModeHost 625 case proto.NetworkIsolationSpec_GROUP: 626 return NetIsolationModeGroup 627 case proto.NetworkIsolationSpec_TASK: 628 return NetIsolationModeTask 629 case proto.NetworkIsolationSpec_NONE: 630 return NetIsolationModeNone 631 default: 632 return NetIsolationModeHost 633 } 634 } 635 636 func NetworkIsolationSpecToProto(spec *NetworkIsolationSpec) *proto.NetworkIsolationSpec { 637 if spec == nil { 638 return nil 639 } 640 return &proto.NetworkIsolationSpec{ 641 Path: spec.Path, 642 Labels: spec.Labels, 643 Mode: netIsolationModeToProto(spec.Mode), 644 } 645 } 646 647 func NetworkIsolationSpecFromProto(pb *proto.NetworkIsolationSpec) *NetworkIsolationSpec { 648 if pb == nil { 649 return nil 650 } 651 return &NetworkIsolationSpec{ 652 Path: pb.Path, 653 Labels: pb.Labels, 654 Mode: netIsolationModeFromProto(pb.Mode), 655 } 656 } 657 658 func dnsConfigToProto(dns *DNSConfig) *proto.DNSConfig { 659 if dns == nil { 660 return nil 661 } 662 663 return &proto.DNSConfig{ 664 Servers: dns.Servers, 665 Searches: dns.Searches, 666 Options: dns.Options, 667 } 668 } 669 670 func dnsConfigFromProto(pb *proto.DNSConfig) *DNSConfig { 671 if pb == nil { 672 return nil 673 } 674 675 return &DNSConfig{ 676 Servers: pb.Servers, 677 Searches: pb.Searches, 678 Options: pb.Options, 679 } 680 }