| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package manager
- import (
- "sync"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/onecloud/pkg/util/losetup"
- )
- var (
- managerObj iManager
- managerInitLock sync.Mutex
- )
- func Init() {
- managerInitLock.Lock()
- defer managerInitLock.Unlock()
- if managerObj == nil {
- managerObj = newManager()
- }
- }
- func ListDevices() (*losetup.Devices, error) {
- return managerObj.listDevices()
- }
- func AttachDevice(filePath string, partScan bool) (*losetup.Device, error) {
- return managerObj.attachDevice(filePath, partScan)
- }
- func DetachDevice(filePath string) error {
- return managerObj.detachDevice(filePath)
- }
- type iManager interface {
- listDevices() (*losetup.Devices, error)
- attachDevice(filePath string, partScan bool) (*losetup.Device, error)
- detachDevice(devPath string) error
- }
- type execType string
- const (
- EXEC_ATTACH execType = "attach"
- EXEC_DETACH execType = "detach"
- )
- type execAttach struct {
- FilePath string
- PartScan bool
- }
- type execDetach struct {
- DevicePath string
- }
- type execOption struct {
- Type execType
- Attach *execAttach
- Detach *execDetach
- result chan execResult
- }
- type execResult struct {
- error error
- attachedDevice *losetup.Device
- }
- func newAttachOption(filePath string, partScan bool) *execOption {
- return &execOption{
- Type: EXEC_ATTACH,
- result: make(chan execResult),
- Attach: &execAttach{
- FilePath: filePath,
- PartScan: partScan,
- },
- }
- }
- func newDetachOption(devPath string) *execOption {
- return &execOption{
- Type: EXEC_DETACH,
- result: make(chan execResult),
- Detach: &execDetach{
- DevicePath: devPath,
- },
- }
- }
- type manager struct {
- execOptCh chan *execOption
- loopMan ILoopManager
- }
- func newManager() iManager {
- loopMan, err := newLoopManager()
- if err != nil {
- log.Fatalf("new loop manager error: %v", err)
- }
- m := &manager{
- execOptCh: make(chan *execOption),
- loopMan: loopMan,
- }
- go func() {
- m.startExec()
- }()
- return m
- }
- func (m *manager) listDevices() (*losetup.Devices, error) {
- return losetup.ListDevices()
- }
- func (m *manager) attachDevice(filePath string, partScan bool) (*losetup.Device, error) {
- opt := newAttachOption(filePath, partScan)
- m.execOptCh <- opt
- result := <-opt.result
- return result.attachedDevice, result.error
- }
- func (m *manager) detachDevice(devPath string) error {
- opt := newDetachOption(devPath)
- m.execOptCh <- opt
- result := <-opt.result
- return result.error
- }
- func (m *manager) startExec() {
- for execOpt := range m.execOptCh {
- switch execOpt.Type {
- case EXEC_ATTACH:
- log.Infof("attach %s", jsonutils.Marshal(execOpt.Attach))
- dev, err := m.loopMan.AttachDevice(execOpt.Attach.FilePath, execOpt.Attach.PartScan)
- execOpt.result <- execResult{
- attachedDevice: dev,
- error: err,
- }
- case EXEC_DETACH:
- log.Infof("detach %s", jsonutils.Marshal(execOpt.Detach))
- err := m.loopMan.DetachDevice(execOpt.Detach.DevicePath)
- execOpt.result <- execResult{
- error: err,
- }
- default:
- err := errors.Errorf("unknown exec type: %s", execOpt.Type)
- execOpt.result <- execResult{
- error: err,
- }
- }
- }
- }
|