func createBlockDevice(label string, opts map[string]string) error { backing := getBackingFileName(label) err := createBackingFile(backing) if err != nil { return err } loopbackCount := getMaxLoopbackCount() + 1 device := fmt.Sprintf("/dev/loop%d", loopbackCount) err = createDeviceNode(device, loopbackCount) if err != nil { return err } // Ignore output. This is to prevent spurious failures from old devices // that were removed, but not detached. exec.Command("losetup", "-d", device).CombinedOutput() err = setupLoopbackDevice(backing, device) if err != nil { return err } // Use default fstype if not specified if _, result := opts["fstype"]; result == false { opts["fstype"] = fs.FstypeDefault } mkfscmd, result := fs.MkfsLookup()[opts["fstype"]] if result == false { return fmt.Errorf("Not found mkfs for %s", opts["fstype"]) } return fs.Mkfs(mkfscmd, label, device) }
// The user wants to create a volume. // No need to actually manifest the volume on the filesystem yet // (until Mount is called). // Name and driver specific options passed through to the ESX host func (d *vmdkDriver) Create(r volume.Request) volume.Response { // Use default fstype if not specified if _, result := r.Options["fstype"]; result == false { r.Options["fstype"] = fs.FstypeDefault } // Get existent filesystem tools supportedFs := fs.MkfsLookup() // Verify the existence of fstype mkfs mkfscmd, result := supportedFs[r.Options["fstype"]] if result == false { msg := "Not found mkfs for " + r.Options["fstype"] msg += "\nSupported filesystems found: " validfs := "" for fs := range supportedFs { if validfs != "" { validfs += ", " + fs } else { validfs += fs } } log.WithFields(log.Fields{"name": r.Name, "fstype": r.Options["fstype"]}).Error("Not found ") return volume.Response{Err: msg + validfs} } errCreate := d.ops.Create(r.Name, r.Options) if errCreate != nil { log.WithFields(log.Fields{"name": r.Name, "error": errCreate}).Error("Create volume failed ") return volume.Response{Err: errCreate.Error()} } // Handle filesystem creation log.WithFields(log.Fields{"name": r.Name, "fstype": r.Options["fstype"]}).Info("Attaching volume and creating filesystem ") dev, errAttach := d.ops.Attach(r.Name, nil) if errAttach != nil { log.WithFields(log.Fields{"name": r.Name, "error": errAttach}).Error("Attach volume failed, removing the volume ") errRemove := d.ops.Remove(r.Name, nil) if errRemove != nil { log.WithFields(log.Fields{"name": r.Name, "error": errRemove}).Warning("Remove volume failed ") } return volume.Response{Err: errAttach.Error()} } device, errGetDevicePath := fs.GetDevicePath(dev) if errGetDevicePath != nil { log.WithFields(log.Fields{"name": r.Name, "error": errGetDevicePath}).Error("Could not find attached device, removing the volume ") errDetach := d.ops.Detach(r.Name, nil) if errDetach != nil { log.WithFields(log.Fields{"name": r.Name, "error": errDetach}).Warning("Detach volume failed ") } errRemove := d.ops.Remove(r.Name, nil) if errRemove != nil { log.WithFields(log.Fields{"name": r.Name, "error": errRemove}).Warning("Remove volume failed ") } return volume.Response{Err: errGetDevicePath.Error()} } errMkfs := fs.Mkfs(mkfscmd, r.Name, device) if errMkfs != nil { log.WithFields(log.Fields{"name": r.Name, "error": errMkfs}).Error("Create filesystem failed, removing the volume ") errDetach := d.ops.Detach(r.Name, nil) if errDetach != nil { log.WithFields(log.Fields{"name": r.Name, "error": errDetach}).Warning("Detach volume failed ") } errRemove := d.ops.Remove(r.Name, nil) if errRemove != nil { log.WithFields(log.Fields{"name": r.Name, "error": errRemove}).Warning("Remove volume failed ") } return volume.Response{Err: errMkfs.Error()} } errDetach := d.ops.Detach(r.Name, nil) if errDetach != nil { log.WithFields(log.Fields{"name": r.Name, "error": errDetach}).Error("Detach volume failed ") return volume.Response{Err: errDetach.Error()} } log.WithFields(log.Fields{"name": r.Name, "fstype": r.Options["fstype"]}).Info("Volume and filesystem created ") return volume.Response{Err: ""} }