func NewHyperClient(proto, addr string, tlsConfig *tls.Config) *HyperClient { var ( inFd uintptr outFd uintptr isTerminalIn = false isTerminalOut = false ) clifile, err := cliconfig.Load(filepath.Join(homedir.Get(), ".docker")) if err != nil { fmt.Fprintf(os.Stdout, "WARNING: Error loading config file %v\n", err) } inFd, isTerminalIn = term.GetFdInfo(os.Stdin) outFd, isTerminalOut = term.GetFdInfo(os.Stdout) return &HyperClient{ client: api.NewClient(proto, addr, tlsConfig), in: os.Stdin, out: os.Stdout, err: os.Stdout, inFd: inFd, outFd: outFd, isTerminalIn: isTerminalIn, isTerminalOut: isTerminalOut, configFile: clifile, } }
func NewHyperClient(proto, addr string, tlsConfig *tls.Config) *HyperClient { var ( inFd uintptr outFd uintptr isTerminalIn = false isTerminalOut = false scheme = "http" ) if tlsConfig != nil { scheme = "https" } // The transport is created here for reuse during the client session tran := &http.Transport{ TLSClientConfig: tlsConfig, } // Why 32? See issue 8035 timeout := 32 * time.Second if proto == "unix" { // no need in compressing for local communications tran.DisableCompression = true tran.Dial = func(_, _ string) (net.Conn, error) { return net.DialTimeout(proto, addr, timeout) } } else { tran.Proxy = http.ProxyFromEnvironment tran.Dial = (&net.Dialer{Timeout: timeout}).Dial } inFd, isTerminalIn = term.GetFdInfo(os.Stdin) outFd, isTerminalOut = term.GetFdInfo(os.Stdout) clifile, err := cliconfig.Load(filepath.Join(homedir.Get(), ".docker")) if err != nil { fmt.Fprintf(os.Stdout, "WARNING: Error loading config file %v\n", err) } return &HyperClient{ proto: proto, addr: addr, configFile: clifile, in: os.Stdin, out: os.Stdout, err: os.Stdout, inFd: inFd, outFd: outFd, isTerminalIn: isTerminalIn, isTerminalOut: isTerminalOut, scheme: scheme, transport: tran, } }
// stdin/stdout <-> conn func containerTtySplice(root, container string, conn net.Conn, isContainer bool) (int, error) { tag, err := runvGetTag(conn) if err != nil { return -1, err } fmt.Printf("tag=%s\n", tag) outFd, isTerminalOut := term.GetFdInfo(os.Stdout) newTty(root, container, tag, outFd, isTerminalOut).monitorTtySize() _, err = term.TtySplice(conn) if err != nil { return -1, err } cmd := &ttyTagCmd{Root: root, Container: "", Tag: tag} if isContainer { cmd.Container = container } conn, err = runvRequest(root, container, RUNV_EXITSTATUS, cmd) if err != nil { fmt.Printf("runvRequest failed: %v\n", err) return -1, err } defer conn.Close() msg, err := hypervisor.ReadVmMessage(conn.(*net.UnixConn)) if err != nil { fmt.Printf("read runv server data failed: %v\n", err) return -1, err } if msg.Code != RUNV_EXITSTATUS { return -1, fmt.Errorf("unexpected respond code") } return int(msg.Message[0]), nil }
func main() { hypervisor.InterfaceCount = 0 var containerInfoList []*hypervisor.ContainerInfo var roots []string var containerId string var err error ocffile := flag.String("config", "", "ocf configure file") kernel := flag.String("kernel", "", "hyper kernel") initrd := flag.String("initrd", "", "hyper initrd") vbox := flag.String("vbox", "", "vbox boot iso") driver := flag.String("driver", "", "hypervisor driver") flag.Parse() if *ocffile == "" { *ocffile = "config.json" } if _, err = os.Stat(*ocffile); os.IsNotExist(err) { fmt.Printf("Please specify ocffile or put config.json under current working directory\n") return } if *vbox == "" { *vbox = "./vbox.iso" } if _, err = os.Stat(*vbox); err == nil { *vbox, err = filepath.Abs(*vbox) if err != nil { fmt.Printf("Cannot get abs path for vbox: %s\n", err.Error()) return } } if *kernel == "" { *kernel = "./kernel" } if _, err = os.Stat(*kernel); err == nil { *kernel, err = filepath.Abs(*kernel) if err != nil { fmt.Printf("Cannot get abs path for kernel: %s\n", err.Error()) return } } if *initrd == "" { *initrd = "./initrd.img" } if _, err = os.Stat(*initrd); err == nil { *initrd, err = filepath.Abs(*initrd) if err != nil { fmt.Printf("Cannot get abs path for initrd: %s\n", err.Error()) return } } if *driver == "" { *driver = "kvm" fmt.Printf("Use default hypervisor KVM\n") } if hypervisor.HDriver, err = driverloader.Probe(*driver); err != nil { fmt.Printf("%s\n", err.Error()) return } podId := fmt.Sprintf("pod-%s", pod.RandStr(10, "alpha")) vmId := fmt.Sprintf("vm-%s", pod.RandStr(10, "alpha")) ocfData, err := ioutil.ReadFile(*ocffile) if err != nil { fmt.Printf("%s\n", err.Error()) return } userPod, err := pod.OCFConvert2Pod(ocfData) if err != nil { fmt.Printf("%s\n", err.Error()) return } mypod := hypervisor.NewPod(podId, userPod) var ( cpu = 1 mem = 128 ) if userPod.Resource.Vcpu > 0 { cpu = userPod.Resource.Vcpu } if userPod.Resource.Memory > 0 { mem = userPod.Resource.Memory } b := &hypervisor.BootConfig{ Kernel: *kernel, Initrd: *initrd, Bios: "", Cbfs: "", Vbox: *vbox, CPU: cpu, Memory: mem, } vm := hypervisor.NewVm(vmId, cpu, mem, false, types.VM_KEEP_NONE) err = vm.Launch(b) if err != nil { fmt.Printf("%s\n", err.Error()) return } sharedDir := path.Join(hypervisor.BaseDir, vm.Id, hypervisor.ShareDirTag) for _, c := range userPod.Containers { var root string var err error containerId = GenerateRandomID() rootDir := path.Join(sharedDir, containerId) os.MkdirAll(rootDir, 0755) rootDir = path.Join(rootDir, "rootfs") if !filepath.IsAbs(c.Image) { root, err = filepath.Abs(c.Image) if err != nil { fmt.Printf("%s\n", err.Error()) return } } else { root = c.Image } err = mount(root, rootDir) if err != nil { fmt.Printf("mount %s to %s failed: %s\n", root, rootDir, err.Error()) return } roots = append(roots, rootDir) containerInfo := &hypervisor.ContainerInfo{ Id: containerId, Rootfs: "rootfs", Image: containerId, Fstype: "dir", } containerInfoList = append(containerInfoList, containerInfo) mypod.AddContainer(containerId, podId, "", []string{}, types.S_POD_CREATED) } qemuResponse := vm.StartPod(mypod, userPod, containerInfoList, nil) if qemuResponse.Data == nil { fmt.Printf("StartPod fail: QEMU response data is nil\n") return } fmt.Printf("result: code %d %s\n", qemuResponse.Code, qemuResponse.Cause) inFd, _ := term.GetFdInfo(os.Stdin) outFd, isTerminalOut := term.GetFdInfo(os.Stdout) oldState, err := term.SetRawTerminal(inFd) if err != nil { return } height, width := getTtySize(outFd, isTerminalOut) winSize := &hypervisor.WindowSize{ Row: uint16(height), Column: uint16(width), } tag := pod.RandStr(8, "alphanum") monitorTtySize(vm, tag, outFd, isTerminalOut) vm.Attach(os.Stdin, os.Stdout, tag, containerId, winSize) qemuResponse = vm.StopPod(mypod, "yes") term.RestoreTerminal(inFd, oldState) for _, root := range roots { umount(root) } if qemuResponse.Data == nil { fmt.Printf("StopPod fail: QEMU response data is nil\n") return } fmt.Printf("result: code %d %s\n", qemuResponse.Code, qemuResponse.Cause) }