Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 Utilities for isolating and swarming. See swarming_test.go for usage exa mples. | 2 Utilities for isolating and swarming. See swarming_test.go for usage exa mples. |
| 3 */ | 3 */ |
| 4 package swarming | 4 package swarming |
| 5 | 5 |
| 6 import ( | 6 import ( |
| 7 "bytes" | 7 "bytes" |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "fmt" | 9 "fmt" |
| 10 "io/ioutil" | 10 "io/ioutil" |
| 11 "os" | 11 "os" |
| 12 "path" | 12 "path" |
| 13 "strconv" | 13 "strconv" |
| 14 "time" | 14 "time" |
| 15 | 15 |
| 16 "github.com/skia-dev/glog" | 16 "github.com/skia-dev/glog" |
| 17 "go.skia.org/infra/go/exec" | 17 "go.skia.org/infra/go/exec" |
| 18 "go.skia.org/infra/go/gitinfo" | 18 "go.skia.org/infra/go/gitinfo" |
| 19 "go.skia.org/infra/go/util" | 19 "go.skia.org/infra/go/util" |
| 20 ) | 20 ) |
| 21 | 21 |
| 22 const ( | 22 const ( |
| 23 » ISOLATE_BINARY = "isolate" | 23 » ISOLATE_BINARY = "isolate" |
| 24 » ISOLATE_SERVER = "isolateserver.appspot.com" | 24 » ISOLATE_SERVER = "isolateserver.appspot.com" |
| 25 » SWARMING_SERVER = "chromium-swarm.appspot.com" | 25 » SWARMING_SERVER = "chromium-swarm.appspot.com" |
| 26 » LUCI_CLIENT_REPO = "https://github.com/luci/client-py" | 26 » LUCI_CLIENT_REPO = "https://github.com/luci/client-py" |
| 27 » IO_TIMEOUT = 20 * time.Minute | 27 » RECOMMENDED_IO_TIMEOUT = 20 * time.Minute |
| 28 » HARD_TIMEOUT = 1 * time.Hour | 28 » RECOMMENDED_HARD_TIMEOUT = 1 * time.Hour |
| 29 » RECOMMENDED_PRIORITY = 90 | 29 » RECOMMENDED_PRIORITY = 90 |
| 30 » RECOMMENDED_EXPIRATION = 4 * time.Hour | 30 » RECOMMENDED_EXPIRATION = 4 * time.Hour |
| 31 ) | 31 ) |
| 32 | 32 |
| 33 type SwarmingClient struct { | 33 type SwarmingClient struct { |
| 34 WorkDir string | 34 WorkDir string |
| 35 IsolatedServer string | 35 IsolatedServer string |
| 36 SwarmingServer string | 36 SwarmingServer string |
| 37 } | 37 } |
| 38 | 38 |
| 39 type SwarmingTask struct { | 39 type SwarmingTask struct { |
| 40 Title string | 40 Title string |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 54 | 54 |
| 55 type ShardOutputFormat struct { | 55 type ShardOutputFormat struct { |
| 56 ExitCode string `json:"exit_code"` | 56 ExitCode string `json:"exit_code"` |
| 57 Output string `json:"output"` | 57 Output string `json:"output"` |
| 58 } | 58 } |
| 59 | 59 |
| 60 type TaskOutputFormat struct { | 60 type TaskOutputFormat struct { |
| 61 Shards []ShardOutputFormat `json:"shards"` | 61 Shards []ShardOutputFormat `json:"shards"` |
| 62 } | 62 } |
| 63 | 63 |
| 64 func (t *SwarmingTask) Trigger(s *SwarmingClient) error { | 64 func (t *SwarmingTask) Trigger(s *SwarmingClient, hardTimeout, ioTimeout time.Du ration) error { |
| 65 swarmingBinary := path.Join(s.WorkDir, "client-py", "swarming.py") | 65 swarmingBinary := path.Join(s.WorkDir, "client-py", "swarming.py") |
| 66 if err := _VerifyBinaryExists(swarmingBinary); err != nil { | 66 if err := _VerifyBinaryExists(swarmingBinary); err != nil { |
| 67 return fmt.Errorf("Could not find swarming binary: %s", err) | 67 return fmt.Errorf("Could not find swarming binary: %s", err) |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Run swarming trigger. | 70 // Run swarming trigger. |
| 71 dumpJSON := path.Join(t.OutputDir, fmt.Sprintf("%s-trigger-output.json", t.Title)) | 71 dumpJSON := path.Join(t.OutputDir, fmt.Sprintf("%s-trigger-output.json", t.Title)) |
| 72 triggerArgs := []string{ | 72 triggerArgs := []string{ |
| 73 "trigger", | 73 "trigger", |
| 74 "--swarming", s.SwarmingServer, | 74 "--swarming", s.SwarmingServer, |
| 75 "--isolate-server", s.IsolatedServer, | 75 "--isolate-server", s.IsolatedServer, |
| 76 "--priority", strconv.Itoa(t.Priority), | 76 "--priority", strconv.Itoa(t.Priority), |
| 77 "--shards", strconv.Itoa(1), | 77 "--shards", strconv.Itoa(1), |
| 78 "--task-name", t.Title, | 78 "--task-name", t.Title, |
| 79 "--dump-json", dumpJSON, | 79 "--dump-json", dumpJSON, |
| 80 "--expiration", strconv.FormatFloat(t.Expiration.Seconds(), 'f', 0, 64), | 80 "--expiration", strconv.FormatFloat(t.Expiration.Seconds(), 'f', 0, 64), |
| 81 » » "--io-timeout", strconv.FormatFloat(IO_TIMEOUT.Seconds(), 'f', 0 , 64), | 81 » » "--io-timeout", strconv.FormatFloat(ioTimeout.Seconds(), 'f', 0, 64), |
| 82 » » "--hard-timeout", strconv.FormatFloat(HARD_TIMEOUT.Seconds(), 'f ', 0, 64), | 82 » » "--hard-timeout", strconv.FormatFloat(hardTimeout.Seconds(), 'f' , 0, 64), |
| 83 "--verbose", | 83 "--verbose", |
| 84 } | 84 } |
| 85 for k, v := range t.Dimensions { | 85 for k, v := range t.Dimensions { |
| 86 triggerArgs = append(triggerArgs, "--dimension", k, v) | 86 triggerArgs = append(triggerArgs, "--dimension", k, v) |
| 87 } | 87 } |
| 88 if t.Idempotent { | 88 if t.Idempotent { |
| 89 triggerArgs = append(triggerArgs, "--idempotent") | 89 triggerArgs = append(triggerArgs, "--idempotent") |
| 90 } | 90 } |
| 91 triggerArgs = append(triggerArgs, t.IsolatedHash) | 91 triggerArgs = append(triggerArgs, t.IsolatedHash) |
| 92 | 92 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 235 } | 235 } |
| 236 var tasksToHashes map[string]string | 236 var tasksToHashes map[string]string |
| 237 if err := json.NewDecoder(bytes.NewReader(dumpFile)).Decode(&tasksToHash es); err != nil { | 237 if err := json.NewDecoder(bytes.NewReader(dumpFile)).Decode(&tasksToHash es); err != nil { |
| 238 return nil, fmt.Errorf("Could not decode %s: %s", dumpJSON, err) | 238 return nil, fmt.Errorf("Could not decode %s: %s", dumpJSON, err) |
| 239 } | 239 } |
| 240 | 240 |
| 241 return tasksToHashes, nil | 241 return tasksToHashes, nil |
| 242 } | 242 } |
| 243 | 243 |
| 244 // Trigger swarming using the specified hashes and dimensions. | 244 // Trigger swarming using the specified hashes and dimensions. |
| 245 func (s *SwarmingClient) TriggerSwarmingTasks(tasksToHashes map[string]string, d imensions map[string]string, priority int, expiration time.Duration, idempotent bool) ([]*SwarmingTask, error) { | 245 func (s *SwarmingClient) TriggerSwarmingTasks(tasksToHashes map[string]string, d imensions map[string]string, priority int, expiration, hardTimeout, ioTimeout ti me.Duration, idempotent bool) ([]*SwarmingTask, error) { |
| 246 tasks := []*SwarmingTask{} | 246 tasks := []*SwarmingTask{} |
| 247 | 247 |
| 248 for taskName, hash := range tasksToHashes { | 248 for taskName, hash := range tasksToHashes { |
| 249 taskOutputDir := path.Join(s.WorkDir, taskName) | 249 taskOutputDir := path.Join(s.WorkDir, taskName) |
| 250 if err := os.MkdirAll(taskOutputDir, 0700); err != nil { | 250 if err := os.MkdirAll(taskOutputDir, 0700); err != nil { |
| 251 return nil, fmt.Errorf("Could not create %s: %s", taskOu tputDir, err) | 251 return nil, fmt.Errorf("Could not create %s: %s", taskOu tputDir, err) |
| 252 } | 252 } |
| 253 task := &SwarmingTask{ | 253 task := &SwarmingTask{ |
| 254 Title: taskName, | 254 Title: taskName, |
| 255 IsolatedHash: hash, | 255 IsolatedHash: hash, |
| 256 OutputDir: taskOutputDir, | 256 OutputDir: taskOutputDir, |
| 257 Dimensions: dimensions, | 257 Dimensions: dimensions, |
| 258 Priority: priority, | 258 Priority: priority, |
| 259 Expiration: expiration, | 259 Expiration: expiration, |
| 260 Idempotent: idempotent, | 260 Idempotent: idempotent, |
| 261 } | 261 } |
| 262 » » if err := task.Trigger(s); err != nil { | 262 » » if err := task.Trigger(s, hardTimeout, ioTimeout); err != nil { |
| 263 return nil, fmt.Errorf("Could not trigger task %s: %s", taskName, err) | 263 return nil, fmt.Errorf("Could not trigger task %s: %s", taskName, err) |
| 264 } | 264 } |
| 265 » » glog.Infof("Triggered the task: %s", task) | 265 » » glog.Infof("Triggered the task: %v", task) |
| 266 tasks = append(tasks, task) | 266 tasks = append(tasks, task) |
| 267 } | 267 } |
| 268 | 268 |
| 269 return tasks, nil | 269 return tasks, nil |
| 270 } | 270 } |
| 271 | 271 |
| 272 func (s *SwarmingClient) Cleanup() { | 272 func (s *SwarmingClient) Cleanup() { |
| 273 if err := os.RemoveAll(s.WorkDir); err != nil { | 273 if err := os.RemoveAll(s.WorkDir); err != nil { |
| 274 glog.Errorf("Could not cleanup swarming work dir: %s", err) | 274 glog.Errorf("Could not cleanup swarming work dir: %s", err) |
| 275 } | 275 } |
| 276 } | 276 } |
| 277 | 277 |
| 278 func _VerifyBinaryExists(binary string) error { | 278 func _VerifyBinaryExists(binary string) error { |
| 279 err := exec.Run(&exec.Command{ | 279 err := exec.Run(&exec.Command{ |
| 280 Name: binary, | 280 Name: binary, |
| 281 Args: []string{"help"}, | 281 Args: []string{"help"}, |
| 282 Timeout: 60 * time.Second, | 282 Timeout: 60 * time.Second, |
| 283 » » LogStdout: true, | 283 » » LogStdout: false, |
|
rmistry
2016/05/18 13:10:48
Eliminating noise in logs.
| |
| 284 LogStderr: true, | 284 LogStderr: true, |
| 285 }) | 285 }) |
| 286 if err != nil { | 286 if err != nil { |
| 287 return fmt.Errorf("Error finding the binary %s: %s", binary, err ) | 287 return fmt.Errorf("Error finding the binary %s: %s", binary, err ) |
| 288 } | 288 } |
| 289 return nil | 289 return nil |
| 290 } | 290 } |
| OLD | NEW |