lxd/storage_pools_utils.go
func doStoragePoolCreateInternal(state *state.State, poolName, poolDescription string, driver string, config map[string]string, isNotification bool) error {
	tryUndo := true
	s, err := storagePoolInit(state, poolName)
	if err != nil {
		return err
	}

	// If this is a clustering notification for a ceph storage, we don't
	// want this node to actually create the pool, as it's already been
	// done by the node that triggered this notification. We just need to
	// create the storage pool directory.
	if s, ok := s.(*storageCeph); ok && isNotification {
		volumeMntPoint := getStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
		return os.MkdirAll(volumeMntPoint, 0711)

	}
	err = s.StoragePoolCreate()
	if err != nil {
		return err
	}
	defer func() {
		if !tryUndo {
			return
		}
		s.StoragePoolDelete()
	}()

	// In case the storage pool config was changed during the pool creation,
	// we need to update the database to reflect this change. This can e.g.
	// happen, when we create a loop file image. This means we append ".img"
	// to the path the user gave us and update the config in the storage
	// callback. So diff the config here to see if something like this has
	// happened.
	postCreateConfig := s.GetStoragePoolWritable().Config
	configDiff, _ := storageConfigDiff(config, postCreateConfig)
	if len(configDiff) > 0 {
		// Create the database entry for the storage pool.
		err = state.Cluster.StoragePoolUpdate(poolName, poolDescription, postCreateConfig)
		if err != nil {
			return fmt.Errorf("Error inserting %s into database: %s", poolName, err)
		}
	}

	// Success, update the closure to mark that the changes should be kept.
	tryUndo = false

	return nil
}
func doStoragePoolCreateInternal(state *state.State, poolName, poolDescription string, driver string, config map[string]string, isNotification bool) error {
	tryUndo := true
	s, err := storagePoolInit(state, poolName)
	if err != nil {
		return err
	}

	// If this is a clustering notification for a ceph storage, we don't
	// want this node to actually create the pool, as it's already been
	// done by the node that triggered this notification. We just need to
	// create the storage pool directory.
	if s, ok := s.(*storageCeph); ok && isNotification {
		volumeMntPoint := getStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
		return os.MkdirAll(volumeMntPoint, 0711)

	}
	err = s.StoragePoolCreate()
	if err != nil {
		return err
	}
	defer func() {
		if !tryUndo {
			return
		}
		s.StoragePoolDelete()
	}()

	// In case the storage pool config was changed during the pool creation,
	// we need to update the database to reflect this change. This can e.g.
	// happen, when we create a loop file image. This means we append ".img"
	// to the path the user gave us and update the config in the storage
	// callback. So diff the config here to see if something like this has
	// happened.
	postCreateConfig := s.GetStoragePoolWritable().Config
	configDiff, _ := storageConfigDiff(config, postCreateConfig)
	if len(configDiff) > 0 {
		// Create the database entry for the storage pool.
		err = state.Cluster.StoragePoolUpdate(poolName, poolDescription, postCreateConfig)
		if err != nil {
			return fmt.Errorf("Error inserting %s into database: %s", poolName, err)
		}
	}

	// Success, update the closure to mark that the changes should be kept.
	tryUndo = false

	return nil
}
// This performs all non-db related work needed to create the pool.