aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]vm/isolated/isolated.go64
1 files changed, 46 insertions, 18 deletions
diff --git a/vm/isolated/isolated.go b/vm/isolated/isolated.go
index dd911394b..fa5b842fd 100644..100755
--- a/vm/isolated/isolated.go
+++ b/vm/isolated/isolated.go
@@ -24,9 +24,11 @@ func init() {
}
type Config struct {
- Targets []string `json:"targets"` // target machines: (hostname|ip)(:port)?
- TargetDir string `json:"target_dir"` // directory to copy/run on target
- TargetReboot bool `json:"target_reboot"` // reboot target on repair
+ Host string `json:"host"` // host ip addr
+ Targets []string `json:"targets"` // target machines: (hostname|ip)(:port)?
+ TargetDir string `json:"target_dir"` // directory to copy/run on target
+ TargetReboot bool `json:"target_reboot"` // reboot target on repair
+ USBDevNums []string `json:"usb_device_num"` // /sys/bus/usb/devices/
}
type Pool struct {
@@ -39,6 +41,7 @@ type instance struct {
os string
targetAddr string
targetPort int
+ index int
closed chan bool
debug bool
sshUser string
@@ -51,6 +54,9 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
if err := config.LoadData(env.Config, cfg); err != nil {
return nil, err
}
+ if cfg.Host == "" {
+ cfg.Host = "127.0.0.1"
+ }
if len(cfg.Targets) == 0 {
return nil, fmt.Errorf("config param targets is empty")
}
@@ -62,9 +68,17 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
return nil, fmt.Errorf("bad target %q: %v", target, err)
}
}
+ if len(cfg.USBDevNums) > 0 {
+ if len(cfg.USBDevNums) != len(cfg.Targets) {
+ return nil, fmt.Errorf("the number of Targets and the number of USBDevNums should be same")
+ }
+ }
if env.Debug && len(cfg.Targets) > 1 {
log.Logf(0, "limiting number of targets from %v to 1 in debug mode", len(cfg.Targets))
cfg.Targets = cfg.Targets[:1]
+ if len(cfg.USBDevNums) > 1 {
+ cfg.USBDevNums = cfg.USBDevNums[:1]
+ }
}
pool := &Pool{
cfg: cfg,
@@ -84,6 +98,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
os: pool.env.OS,
targetAddr: targetAddr,
targetPort: targetPort,
+ index: index,
closed: make(chan bool),
debug: pool.env.Debug,
sshUser: pool.env.SSHUser,
@@ -99,6 +114,9 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
return nil, err
}
+ // Remount to writable.
+ inst.ssh("mount -o remount,rw /")
+
// Create working dir if doesn't exist.
inst.ssh("mkdir -p '" + inst.cfg.TargetDir + "'")
@@ -117,7 +135,7 @@ func (inst *instance) Forward(port int) (string, error) {
return "", fmt.Errorf("isolated: Forward port is zero")
}
inst.forwardPort = port
- return fmt.Sprintf("127.0.0.1:%v", port), nil
+ return fmt.Sprintf(inst.cfg.Host+":%v", port), nil
}
func (inst *instance) ssh(command string) error {
@@ -175,26 +193,36 @@ func (inst *instance) repair() error {
log.Logf(2, "isolated: trying to ssh")
if err := inst.waitForSSH(30 * time.Minute); err == nil {
if inst.cfg.TargetReboot {
- log.Logf(2, "isolated: trying to reboot")
- inst.ssh("reboot") // reboot will return an error, ignore it
- if err := inst.waitForReboot(5 * 60); err != nil {
- log.Logf(2, "isolated: machine did not reboot")
- return err
+ if len(inst.cfg.USBDevNums) > 0 {
+ log.Logf(2, "isolated: trying to reboot by USB authorization")
+ usbAuth := fmt.Sprintf("%s%s%s", "/sys/bus/usb/devices/", inst.cfg.USBDevNums[inst.index], "/authorized")
+ if err := ioutil.WriteFile(usbAuth, []byte("0"), 0); err != nil {
+ log.Logf(2, "isolated: failed to turn off the device")
+ return err
+ }
+ if err := ioutil.WriteFile(usbAuth, []byte("1"), 0); err != nil {
+ log.Logf(2, "isolated: failed to turn on the device")
+ return err
+ }
+ } else {
+ log.Logf(2, "isolated: ssh succeeded, trying to reboot by ssh")
+ inst.ssh("reboot") // reboot will return an error, ignore it
}
- log.Logf(2, "isolated: rebooted wait for comeback")
- if err := inst.waitForSSH(30 * time.Minute); err != nil {
- log.Logf(2, "isolated: machine did not comeback")
- return err
- }
- log.Logf(2, "isolated: reboot succeeded")
- } else {
- log.Logf(2, "isolated: ssh succeeded")
}
+ if err := inst.waitForReboot(5 * 60); err != nil {
+ log.Logf(2, "isolated: machine did not reboot")
+ return err
+ }
+ log.Logf(2, "isolated: rebooted wait for comeback")
+ if err := inst.waitForSSH(30 * time.Minute); err != nil {
+ log.Logf(0, "isolated: machine did not comeback")
+ return err
+ }
+ log.Logf(2, "isolated: reboot succeeded")
} else {
log.Logf(2, "isolated: ssh failed")
return fmt.Errorf("SSH failed")
}
-
return nil
}