func (dc *DiskContext) remove(result chan<- api.Result) { if result == nil { result = make(chan api.Result, 4) } if dc.IsDir() { result <- api.NewResultBase(dc.Name, true, "no need to unplug") return } go func() { r := make(chan VmEvent, 4) dc.sandbox.DCtx.RemoveDisk(dc.sandbox, dc.DiskDescriptor, &VolumeUnmounted{Name: dc.Name, Success: true}, r) ev, ok := <-r if !ok { dc.failed() result <- api.NewResultBase(dc.Name, false, "disk remove session broken") return } _, ok = ev.(*VolumeUnmounted) if !ok { dc.failed() result <- api.NewResultBase(dc.Name, false, "disk remove failed") return } result <- api.NewResultBase(dc.Name, true, "") }() }
func (nc *NetworkContext) removeInterface(id string, result chan api.Result) { if inf, ok := nc.idMap[id]; !ok { nc.sandbox.Log(WARNING, "trying remove a non-exist interface %s", id) result <- api.NewResultBase(id, true, "not exist") return } else if inf.HostDevice == "" { // a virtual interface delete(nc.idMap, id) delete(nc.lo, inf.IpAddr) result <- api.NewResultBase(id, true, "") return } else { nc.slotLock.Lock() defer nc.slotLock.Unlock() if _, ok := nc.eth[inf.Index]; !ok { delete(nc.idMap, id) nc.sandbox.Log(INFO, "non-configured network device %d remove failed", inf.Index) result <- api.NewResultBase(id, true, "not configured eth") return } var devChan chan VmEvent = make(chan VmEvent, 1) nc.sandbox.Log(DEBUG, "remove network card %d: %s", inf.Index, inf.IpAddr) nc.sandbox.DCtx.RemoveNic(nc.sandbox, inf, &NetDevRemovedEvent{Index: inf.Index}, devChan) go func() { ev, ok := <-devChan if !ok { return } success := true message := "" if fe, ok := ev.(*DeviceFailed); ok { success = false message = "unplug failed" if inf, ok := fe.Session.(*NetDevRemovedEvent); ok { nc.sandbox.Log(ERROR, "interface remove failed: %#v", inf) } } nc.slotLock.Lock() defer nc.slotLock.Unlock() nc.freeSlot(inf.Index) nc.cleanupInf(inf) result <- api.NewResultBase(id, success, message) }() } }
func (cc *ContainerContext) add(wgDisk *sync.WaitGroup, result chan api.Result) { wgDisk.Wait() for vn, vcs := range cc.Volumes { vol, ok := cc.sandbox.volumes[vn] if !ok || !vol.isReady() { cc.Log(ERROR, "vol %s is failed to insert", vn) result <- api.NewResultBase(cc.Id, false, "volume failed") return } for _, mp := range vcs.MountPoints { if vol.IsDir() { cc.Log(DEBUG, "volume (fs mapping) %s is ready", vn) cc.fsmap = append(cc.fsmap, &hyperstartapi.FsmapDescriptor{ Source: vol.Filename, Path: mp.Path, ReadOnly: mp.ReadOnly, DockerVolume: vol.DockerVolume, }) } else { cc.Log(DEBUG, "volume (disk) %s is ready", vn) cc.vmVolumes = append(cc.vmVolumes, &hyperstartapi.VolumeDescriptor{ Device: vol.DeviceName, Addr: vol.ScsiAddr, Mount: mp.Path, Fstype: vol.Fstype, ReadOnly: mp.ReadOnly, DockerVolume: vol.DockerVolume, }) } } } if !cc.root.isReady() { result <- api.NewResultBase(cc.Id, false, "root volume insert failed") return } if cc.sandbox.LogLevel(TRACE) { vmspec := cc.VmSpec() cc.Log(TRACE, "resource ready for container: %#v", vmspec) } cc.Log(INFO, "all images and volume resources have been added to sandbox") result <- api.NewResultBase(cc.Id, true, "") }
func (ctx *VmContext) RemoveVolume(name string, result chan<- api.Result) { ctx.lock.Lock() defer ctx.lock.Unlock() disk, ok := ctx.volumes[name] if !ok { ctx.Log(WARNING, "volume %s not exist", name) result <- api.NewResultBase(name, true, "not exist") return } if disk.containers() > 0 { ctx.Log(ERROR, "cannot remove a in use volume %s", name) result <- api.NewResultBase(name, false, "in use") return } ctx.Log(INFO, "remove disk %s", name) delete(ctx.volumes, name) disk.remove(result) }
func (dc *DiskContext) insert(result chan api.Result) { if result == nil { result = make(chan api.Result, 4) } if dc.isReady() { result <- api.NewResultBase(dc.Name, true, "already inserted") return } dc.ScsiId = dc.sandbox.nextScsiId() usage := "volume" if dc.isRootVol { usage = "image" } go func() { r := make(chan VmEvent, 4) dc.sandbox.DCtx.AddDisk(dc.sandbox, usage, dc.DiskDescriptor, r) ev, ok := <-r if !ok { dc.failed() result <- api.NewResultBase(dc.Name, false, "disk insert session broken") return } de, ok := ev.(*BlockdevInsertedEvent) if !ok { dc.failed() result <- api.NewResultBase(dc.Name, false, "disk insert failed") return } dc.DeviceName = de.DeviceName dc.ScsiAddr = de.ScsiAddr result <- api.NewResultBase(dc.Name, true, "") dc.inserted() }() }
func (vm *Vm) Shutdown() api.Result { if vm.ctx.current != StateRunning { return api.NewResultBase(vm.Id, false, "not in running state") } Status, err := vm.GetResponseChan() if err != nil { return api.NewResultBase(vm.Id, false, "fail to get response chan") } defer vm.ReleaseResponseChan(Status) vm.Hub <- &ShutdownCommand{} for { Response, ok := <-Status if !ok { return api.NewResultBase(vm.Id, false, "status channel broken") } glog.V(1).Infof("Got response: %d: %s", Response.Code, Response.Cause) if Response.Code == types.E_VM_SHUTDOWN { return api.NewResultBase(vm.Id, true, "set sandbox config successfully") } } }
func (ctx *VmContext) AddVolume(vol *api.VolumeDescription, result chan api.Result) { ctx.lock.Lock() defer ctx.lock.Unlock() if _, ok := ctx.volumes[vol.Name]; ok { estr := fmt.Sprintf("duplicate volume %s", vol.Name) ctx.Log(WARNING, estr) result <- api.NewResultBase(vol.Name, true, estr) return } dc := NewDiskContext(ctx, vol) if vol.IsDir() { ctx.Log(INFO, "return volume add success for dir %s", vol.Name) result <- api.NewResultBase(vol.Name, true, "") } else { ctx.Log(DEBUG, "insert disk for volume %s", vol.Name) dc.insert(result) } ctx.volumes[vol.Name] = dc }
func (vm *Vm) WaitInit() api.Result { Status, err := vm.GetResponseChan() if err != nil { vm.ctx.Log(ERROR, "failed to get status chan to monitor startpod: %v", err) return api.NewResultBase(vm.Id, false, err.Error()) } defer vm.ReleaseResponseChan(Status) for { s, ok := <-Status if !ok { return api.NewResultBase(vm.Id, false, "status channel broken") } switch s.Code { case types.E_OK: return api.NewResultBase(vm.Id, true, "set sandbox config successfully") case types.E_FAILED, types.E_VM_SHUTDOWN: return api.NewResultBase(vm.Id, false, "set sandbox config failed") default: vm.ctx.Log(DEBUG, "got message %#v while waiting start pod command finish") } } }
func (ctx *VmContext) RemoveContainer(id string, result chan<- api.Result) { ctx.lock.Lock() defer ctx.lock.Unlock() cc, ok := ctx.containers[id] if !ok { ctx.Log(WARNING, "container %s not exist", id) result <- api.NewResultBase(id, true, "not exist") return } for v := range cc.Volumes { if vol, ok := ctx.volumes[v]; ok { vol.unwait(id) } } cc.root.unwait(id) ctx.Log(INFO, "remove container %s", id) delete(ctx.containers, id) cc.root.remove(result) }