	}

	// from a quick read its "safe" to unconditionally try to delete
	// bricks. TODO: find out if that is true with functional tests
	reclaimed, err := DestroyBricks(db, executor, brick_entries)
	if err!= nil {
		logger.LogError("failed to destory bricks during cleanup: %v", err)
	}
	return db.Update(func(tx *bolt.Tx) error {
		for _, brick := range brick_entries {
			v.removeBrickFromDb(tx, brick)
		}
		// update the device' free/used space after removing bricks
		for _, b := range brick_entries {
			if reclaim, found := reclaimed[b.Info.DeviceId]; found {
				if!reclaim {
					// nothing reclaimed, no need to update the DeviceEntry
					continue
				}

				device, err := NewDeviceEntryFromId(tx, b.Info.DeviceId)
				if err!= nil {
					logger.Err(err)
					return err
				}

				// Deallocate space on device
				device.StorageFree(device.SpaceNeeded(b.Info.Size, float64(v.Info.Snapshot.Factor)).Total)
				device.Save(tx)
			}
		}

		if v.Info.Cluster!= "" {
			cluster, err := NewClusterEntryFromId(tx, v.Info.Cluster)
			if err == nil {
				cluster.VolumeDelete(v.Info.Id)
				cluster.Save(tx)
			}
		}
		v.Delete(tx)
		return nil
	})
}

func (v *VolumeEntry) createOneShot(db wdb.DB,
	executor executors.Executor) (e error) {

	var brick_entries []*BrickEntry
	// On any error, remove the volume
	defer func() {
		if e!= nil {
			v.cleanupCreateVolume(db, executor, brick_entries)
		}
	}()

	brick_entries, e = v.createVolumeComponents(db)
	if e!= nil {
		return e
	}
	return v.createVolumeExec(db, executor, brick_entries)
}

func (v *VolumeEntry) createVolumeComponents(db wdb.DB) (
	brick_entries []*BrickEntry, e error) {

	// Get list of clusters
	var possibleClusters []string
	if len(v.Info.Clusters) == 0 {
		err := db.View(func(tx *bolt.Tx) error {
			var err error
			possibleClusters, err = ClusterList(tx)
			return err
		})
		if err!= nil {
			return brick_entries, err
		}
	} else {
		possibleClusters = v.Info.Clusters
	}

	cr := ClusterReq{v.Info.Block, v.Info.Name}
	possibleClusters, err := eligibleClusters(db, cr, possibleClusters)
	if err!= nil {
		return brick_entries, err
	}
	if len(possibleClusters) == 0 {
		logger.LogError("No clusters eligible to satisfy create volume request")
		return brick_entries, ErrNoSpace
	}
	logger.Debug("Using the following clusters: %+v", possibleClusters)

	return v.saveCreateVolume(db, possibleClusters)
}

func (v *VolumeEntry) createVolumeExec(db wdb.DB,
	executor executors.Executor,
	brick_entries []*BrickEntry) (e error) {

	// Create the bricks on the nodes
	e = CreateBricks(db, executor, brick_entries)
	if e!= nil {
		return
	}

	// Create GlusterFS volume
	return v.createVolume(db, executor, brick_entries)
}

func (v *VolumeEntry) saveCreateVolume(db wdb.DB,
	possibleClusters []string) (brick_entries []*BrickEntry, err error) {

	err = db.Update(func(tx *bolt.Tx) error {
		txdb := wdb.WrapTx(tx)
		// For each cluster look for storage space for this volume
		brick_entries, err = v.tryAllocateBricks(txdb, possibleClusters)
		if err!= nil {
			return err
		}
		if brick_entries == nil {
			// Map all 'valid' errors to NoSpace here:
			// Only the last such error could get propagated down,
			// so it does not make sense to hand the granularity on.
			// But for other callers (Expand), we keep it.
			return ErrNoSpace
		}

		err = v.updateMountInfo(txdb)
		if err!= nil {
			return err
		}

		// Save volume information
		if v.Info.Block {
			if err := v.SetRawCapacity(v.Info.Size); err!= nil {
				return err
			}
		}
		err := v.Save(tx)
		if err!= nil {
			return err
		}

		// Save cluster
		cluster, err := NewClusterEntryFromId(tx, v.Info.Cluster)
		if err!= nil {
			return err
		}
		cluster.VolumeAdd(v.Info.Id)
		return cluster.Save(tx)
	})
	return
}

func (v *VolumeEntry) deleteVolumeExec(db wdb.RODB,
	executor executors.Executor,
	brick_entries []*BrickEntry,
	sshhost string) (map[string]bool, error) {

	// Determine if we can destroy the volume
	volumePresent := true
	err := executor.VolumeDestroyCheck(sshhost, v.Info.Name)
	if err!= nil {
		if _, ok := err.(*executors.VolumeDoesNotExistErr); ok {
			volumePresent = false
		} else {
			logger.Err(err)
			return nil, err
		}
	}

	// Determine if the bricks can be destroyed
	err = v.checkBricksCanBeDestroyed(db, executor, brick_entries)
	if err!= nil {
		logger.Err(err)
		return nil, err
	}

	if volumePresent {
		// :TODO: What if the host is no longer available, we may need to try others
		// Stop volume
		err = executor.VolumeDestroy(sshhost, v.Info.Name)
		if err!= nil {
			logger.LogError("Unable to delete volume: %v", err)
			return nil, err
		}
	} else {
		logger.Warning("not attempting to delete missing volume %v", v.Info.Name)
	}

	// Destroy bricks
	space_reclaimed, err := DestroyBricks(db, executor, brick_entries)
	if err!= nil {
		logger.LogError("Unable to delete bricks: %v", err)
		return nil, err
	}

	return space_reclaimed, nil
}

func (v *VolumeEntry) saveDeleteVolume(db wdb.DB,
	brick_entries []*BrickEntry) error {

	// Remove from entries from the db
	return db.Update(func(tx *bolt.Tx) error {
		for _, brick := range brick_entries {
			err := v.removeBrickFromDb(tx, brick)
			if err!= nil {
				logger.Err(err)
				// Everything is destroyed anyways, just keep deleting the others
				// Do not return here
			}
		}

		// Remove volume from cluster
		cluster, err := NewClusterEntryFromId(tx, v.Info.Cluster)
		if err!= nil {
			logger.Err(err)
			// Do not return here.. keep going
		}
		cluster.VolumeDelete(v.Info.Id)

		err = cluster.Save(tx)
		if err!= nil {
			logger.Err(err)
			// Do not return here.. keep going
		}

		// Delete volume
		v.Delete(tx)

		return nil
	})
}

func (v *VolumeEntry) manageHostFromBricks(db wdb.DB,
	brick_entries []*BrickEntry) (sshhost string, err error) {

	err = db.View(func(tx *bolt.Tx) error {
		for _, brick := range brick_entries {
			node, err := NewNodeEntryFromId(tx, brick.Info.NodeId)
			if err!= nil {
				return err
			}
			sshhost = node