// handleRequest runs the task-specific handler and sends the results to the // request's response hook. func (t *task) handleRequest(req *acomm.Request) { defer t.waitgroup.Done() // Run the task-specific request handler result, streamAddr, taskErr := t.handler(req) // Note: The acomm calls log the error already, but we want to have a log // of the request and response data as well. resp, err := acomm.NewResponse(req, result, streamAddr, taskErr) if err != nil { log.WithFields(log.Fields{ "task": t.name, "req": req, "taskResult": result, "taskErr": taskErr, "error": err, }).Error("failed to create response") return } if err := req.Respond(resp); err != nil { log.WithFields(log.Fields{ "task": t.name, "req": req, "taskResult": result, "taskErr": taskErr, "error": err, }).Error("failed to send response") return } }
// DiskInfo is a task handler to retrieve information about disks. func (s *Simple) DiskInfo(req *acomm.Request) (interface{}, *url.URL, error) { var args CPUInfoArgs if err := req.UnmarshalArgs(&args); err != nil { return nil, nil, err } if args.GuestID == "" { return nil, nil, errors.New("missing guest_id") } result := &DiskInfoResult{ &DiskInfo{ Device: "vda1", Size: 10 * (1024 * 1024 * 1024), // 10 GB in bytes }, } return result, nil, nil }
// DelayedResp is a task handler that waits a specified time before returning. func (s *Simple) DelayedResp(req *acomm.Request) (interface{}, *url.URL, error) { var args DelayedRespArgs if err := req.UnmarshalArgs(&args); err != nil { return nil, nil, err } if args.Delay <= 0 { return nil, nil, errors.New("delay must be positive") } start := time.Now() time.Sleep(time.Second * args.Delay) result := &DelayedRespResult{ Delay: args.Delay, ReceivedAt: start, RespondedAt: time.Now(), } return result, nil, nil }
// CPUInfo is a task handler to retrieve information about CPUs. func (s *Simple) CPUInfo(req *acomm.Request) (interface{}, *url.URL, error) { var args CPUInfoArgs if err := req.UnmarshalArgs(&args); err != nil { return nil, nil, err } if args.GuestID == "" { return nil, nil, errors.New("missing guest_id") } result := &CPUInfoResult{ &CPUInfo{ Processor: 0, MHz: 2600, }, &CPUInfo{ Processor: 1, MHz: 2600, }, } return result, nil, nil }
// SystemStatus is a task handler to retrieve info look up and return system // information. It depends on and makes requests for several other tasks. func (s *Simple) SystemStatus(req *acomm.Request) (interface{}, *url.URL, error) { var args SystemStatusArgs if err := req.UnmarshalArgs(&args); err != nil { return nil, nil, err } if args.GuestID == "" { return nil, nil, errors.New("missing guest_id") } // Prepare multiple requests multiRequest := acomm.NewMultiRequest(s.tracker, 0) cpuReq, err := acomm.NewRequest("CPUInfo", s.tracker.URL().String(), &CPUInfoArgs{GuestID: args.GuestID}, nil, nil) if err != nil { return nil, nil, err } diskReq, err := acomm.NewRequest("DiskInfo", s.tracker.URL().String(), &DiskInfoArgs{GuestID: args.GuestID}, nil, nil) if err != nil { return nil, nil, err } requests := map[string]*acomm.Request{ "CPUInfo": cpuReq, "DiskInfo": diskReq, } for name, req := range requests { if err := multiRequest.AddRequest(name, req); err != nil { continue } if err := acomm.Send(s.config.CoordinatorURL(), req); err != nil { multiRequest.RemoveRequest(req) continue } } // Wait for the results responses := multiRequest.Responses() result := &SystemStatusResult{} if resp, ok := responses["CPUInfo"]; ok { if err := resp.UnmarshalResult(&(result.CPUs)); err != nil { log.WithFields(log.Fields{ "name": "CPUInfo", "resp": resp, "error": err, }).Error("failed to unarshal result") } } if resp, ok := responses["DiskInfo"]; ok { if err := resp.UnmarshalResult(&(result.Disks)); err != nil { log.WithFields(log.Fields{ "name": "DiskInfo", "resp": resp, "error": err, }).Error("failed to unarshal result") } } return result, nil, nil }