func createHyperPod(f factory.Factory, spec *specs.Spec, defaultCpus int, defaultMemory int) (*HyperPod, error) { podId := fmt.Sprintf("pod-%s", pod.RandStr(10, "alpha")) userPod := pod.ConvertOCF2PureUserPod(spec) podStatus := hypervisor.NewPod(podId, userPod, nil) cpu := defaultCpus if userPod.Resource.Vcpu > 0 { cpu = userPod.Resource.Vcpu } mem := defaultMemory if userPod.Resource.Memory > 0 { mem = userPod.Resource.Memory } kernel := chooseKernel(spec) initrd := chooseInitrd(spec) glog.V(3).Infof("Using kernel: %s; Initrd: %s; vCPU: %d; Memory %d", kernel, initrd, cpu, mem) var ( vm *hypervisor.Vm err error ) if len(kernel) == 0 && len(initrd) == 0 { vm, err = f.GetVm(cpu, mem) if err != nil { glog.V(1).Infof("Create VM failed with default kernel config: %s", err.Error()) return nil, err } glog.V(3).Infof("Creating VM with default kernel config") } else if len(kernel) == 0 || len(initrd) == 0 { // if user specify a kernel, they must specify an initrd at the same time return nil, fmt.Errorf("You must specify an initrd if you specify a kernel, or vice-versa") } else { boot := &hypervisor.BootConfig{ CPU: cpu, Memory: mem, Kernel: kernel, Initrd: initrd, } vm, err = hypervisor.GetVm("", boot, true, false) if err != nil { glog.V(1).Infof("Create VM failed: %s", err.Error()) return nil, err } glog.V(3).Infof("Creating VM with specific kernel config") } Response := vm.StartPod(podStatus, userPod, nil, nil) if Response.Data == nil { vm.Kill() glog.V(1).Infof("StartPod fail: QEMU response data is nil\n") return nil, fmt.Errorf("StartPod fail") } glog.V(1).Infof("result: code %d %s\n", Response.Code, Response.Cause) hp := &HyperPod{ userPod: userPod, podStatus: podStatus, vm: vm, Containers: make(map[string]*Container), Processes: make(map[string]*Process), } // create Listener process running in its own netns if err = hp.startNsListener(); err != nil { hp.reap() glog.V(1).Infof("start ns listener fail: %s\n", err.Error()) return nil, err } return hp, nil }
func (daemon *Daemon) StartPod(podId, podArgs, vmId string, config interface{}, lazy, autoremove bool, keep int) (int, string, error) { var ( podData []byte err error mypod *hypervisor.Pod vm *hypervisor.Vm = nil ) if podArgs == "" { var ok bool mypod, ok = daemon.PodList[podId] if !ok { return -1, "", fmt.Errorf("Can not find the POD instance of %s", podId) } podData, err = daemon.GetPodByName(podId) if err != nil { return -1, "", err } } else { podData = []byte(podArgs) if err := daemon.CreatePod(podId, podArgs, nil, autoremove); err != nil { glog.Error(err.Error()) return -1, "", err } mypod = daemon.PodList[podId] } userPod, err := pod.ProcessPodBytes(podData) if err != nil { return -1, "", err } defer func() { if vm != nil && err != nil && vmId == "" { daemon.KillVm(vm.Id) } }() if vmId == "" { glog.V(1).Infof("The config: kernel=%s, initrd=%s", daemon.Kernel, daemon.Initrd) 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{ CPU: cpu, Memory: mem, Kernel: daemon.Kernel, Initrd: daemon.Initrd, Bios: daemon.Bios, Cbfs: daemon.Cbfs, Vbox: daemon.VboxImage, } vm = daemon.NewVm("", cpu, mem, lazy, keep) err = vm.Launch(b) if err != nil { return -1, "", err } daemon.AddVm(vm) } else { var ok bool vm, ok = daemon.VmList[vmId] if !ok { err = fmt.Errorf("The VM %s doesn't exist", vmId) return -1, "", err } /* FIXME: check if any pod is running on this vm? */ glog.Infof("find vm:%s", vm.Id) if userPod.Resource.Vcpu != vm.Cpu { err = fmt.Errorf("The new pod's cpu setting is different with the VM's cpu") return -1, "", err } if userPod.Resource.Memory != vm.Mem { err = fmt.Errorf("The new pod's memory setting is different with the VM's memory") return -1, "", err } } fmt.Printf("POD id is %s\n", podId) containerInfoList, volumeInfoList, err := daemon.ParsePod(mypod, userPod, vm.Id) if err != nil { return -1, "", err } vmResponse := vm.StartPod(mypod, userPod, containerInfoList, volumeInfoList) if vmResponse.Data == nil { err = fmt.Errorf("VM response data is nil") return vmResponse.Code, vmResponse.Cause, err } data := vmResponse.Data.([]byte) err = daemon.UpdateVmData(vm.Id, data) if err != nil { glog.Error(err.Error()) return -1, "", err } // add or update the Vm info for POD if err := daemon.UpdateVmByPod(podId, vm.Id); err != nil { glog.Error(err.Error()) return -1, "", err } // XXX we should not close vmStatus chan, it will be closed in shutdown process return vmResponse.Code, vmResponse.Cause, nil }
func (daemon *Daemon) StartPod(podId, podArgs, vmId string, config interface{}, lazy, autoremove bool, keep int, streams []*hypervisor.TtyIO) (int, string, error) { glog.V(1).Infof("podArgs: %s", podArgs) var ( podData []byte err error mypod *hypervisor.Pod vm *hypervisor.Vm = nil ) mypod, podData, err = daemon.GetPod(podId, podArgs, autoremove) if err != nil { return -1, "", err } userPod, err := daemon.ProcessPodBytes(podData, podId) if err != nil { return -1, "", err } if !userPod.Tty && streams != nil && len(streams) > 0 { cause := "Spec does not support TTY, but IO streams are provided" return -1, cause, errors.New(cause) } vm, err = daemon.GetVM(vmId, &userPod.Resource, lazy, keep) if err != nil { return -1, "", err } defer func() { if vm != nil && err != nil && vmId == "" { daemon.KillVm(vm.Id) } }() containerInfoList, volumeInfoList, err := daemon.PreparePod(mypod, userPod, vm.Id) if err != nil { return -1, "", err } for idx, str := range streams { if idx >= len(userPod.Containers) { break } err = vm.Attach(str.Stdin, str.Stdout, str.ClientTag, containerInfoList[idx].Id, str.Callback, nil) if err != nil { glog.Errorf("Failed to attach client %s before start pod", str.ClientTag) return -1, "", err } glog.V(1).Infof("Attach client %s before start pod", str.ClientTag) } vmResponse := vm.StartPod(mypod, userPod, containerInfoList, volumeInfoList) if streams != nil && len(streams) > 0 && vmResponse.Code == types.E_OK { return 0, "", nil } if vmResponse.Data == nil { err = fmt.Errorf("VM response data is nil") return vmResponse.Code, vmResponse.Cause, err } data := vmResponse.Data.([]byte) err = daemon.UpdateVmData(vm.Id, data) if err != nil { glog.Error(err.Error()) return -1, "", err } // add or update the Vm info for POD if err := daemon.UpdateVmByPod(podId, vm.Id); err != nil { glog.Error(err.Error()) return -1, "", err } // XXX we should not close vmStatus chan, it will be closed in shutdown process return vmResponse.Code, vmResponse.Cause, nil }