lxd/storage_btrfs.go
func (s *storageBtrfs) ContainerCreateFromImage(container container, fingerprint string, tracker *ioprogress.ProgressTracker) error {
	logger.Debugf("Creating BTRFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)

	source := s.pool.Config["source"]
	if source == "" {
		return fmt.Errorf("no \"source\" property found for the storage pool")
	}

	_, err := s.StoragePoolMount()
	if err != nil {
		return errors.Wrap(err, "Failed to mount storage pool")
	}

	// We can only create the btrfs subvolume under the mounted storage
	// pool. The on-disk layout for containers on a btrfs storage pool will
	// thus be
	// ${LXD_DIR}/storage-pools/<pool>/containers/. The btrfs tool will
	// complain if the intermediate path does not exist, so create it if it
	// doesn't already.
	containerSubvolumePath := s.getContainerSubvolumePath(s.pool.Name)
	if !shared.PathExists(containerSubvolumePath) {
		err := os.MkdirAll(containerSubvolumePath, containersDirMode)
		if err != nil {
			return errors.Wrap(err, "Failed to create volume directory")
		}
	}

	// Mountpoint of the image:
	// ${LXD_DIR}/images/<fingerprint>
	imageMntPoint := getImageMountPoint(s.pool.Name, fingerprint)
	imageStoragePoolLockID := getImageCreateLockID(s.pool.Name, fingerprint)
	lxdStorageMapLock.Lock()
	if waitChannel, ok := lxdStorageOngoingOperationMap[imageStoragePoolLockID]; ok {
		lxdStorageMapLock.Unlock()
		if _, ok := <-waitChannel; ok {
			logger.Warnf("Received value over semaphore, this should not have happened")
		}
	} else {
		lxdStorageOngoingOperationMap[imageStoragePoolLockID] = make(chan bool)
		lxdStorageMapLock.Unlock()

		var imgerr error
		if !shared.PathExists(imageMntPoint) || !isBtrfsSubVolume(imageMntPoint) {
			imgerr = s.ImageCreate(fingerprint, tracker)
		}

		lxdStorageMapLock.Lock()
		if waitChannel, ok := lxdStorageOngoingOperationMap[imageStoragePoolLockID]; ok {
			close(waitChannel)
			delete(lxdStorageOngoingOperationMap, imageStoragePoolLockID)
		}
		lxdStorageMapLock.Unlock()

		if imgerr != nil {
			return errors.Wrap(imgerr, "Failed to create image volume")
		}
	}

	// Create a rw snapshot at
	// ${LXD_DIR}/storage-pools/<pool>/containers/<name>
	// from the mounted ro image snapshot mounted at
	// ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint>
	containerSubvolumeName := getContainerMountPoint(container.Project(), s.pool.Name, container.Name())
	err = s.btrfsPoolVolumesSnapshot(imageMntPoint, containerSubvolumeName, false, false)
	if err != nil {
		return errors.Wrap(err, "Failed to storage pool volume snapshot")
	}

	// Create the mountpoint for the container at:
	// ${LXD_DIR}/containers/<name>
	err = createContainerMountpoint(containerSubvolumeName, container.Path(), container.IsPrivileged())
	if err != nil {
		return errors.Wrap(err, "Failed to create container mountpoint")
	}

	logger.Debugf("Created BTRFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
	err = container.TemplateApply("create")
	if err != nil {
		return errors.Wrap(err, "Failed to apply container template")
	}
	return nil
}
func (s *storageBtrfs) ContainerCreateFromImage(container container, fingerprint string, tracker *ioprogress.ProgressTracker) error {
	logger.Debugf("Creating BTRFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)

	source := s.pool.Config["source"]
	if source == "" {
		return fmt.Errorf("no \"source\" property found for the storage pool")
	}

	_, err := s.StoragePoolMount()
	if err != nil {
		return errors.Wrap(err, "Failed to mount storage pool")
	}

	// We can only create the btrfs subvolume under the mounted storage
	// pool. The on-disk layout for containers on a btrfs storage pool will
	// thus be
	// ${LXD_DIR}/storage-pools/<pool>/containers/. The btrfs tool will
	// complain if the intermediate path does not exist, so create it if it
	// doesn't already.
	containerSubvolumePath := s.getContainerSubvolumePath(s.pool.Name)
	if !shared.PathExists(containerSubvolumePath) {
		err := os.MkdirAll(containerSubvolumePath, containersDirMode)
		if err != nil {
			return errors.Wrap(err, "Failed to create volume directory")
		}
	}

	// Mountpoint of the image:
	// ${LXD_DIR}/images/<fingerprint>
	imageMntPoint := getImageMountPoint(s.pool.Name, fingerprint)
	imageStoragePoolLockID := getImageCreateLockID(s.pool.Name, fingerprint)
	lxdStorageMapLock.Lock()
	if waitChannel, ok := lxdStorageOngoingOperationMap[imageStoragePoolLockID]; ok {
		lxdStorageMapLock.Unlock()
		if _, ok := <-waitChannel; ok {
			logger.Warnf("Received value over semaphore, this should not have happened")
		}
	} else {
		lxdStorageOngoingOperationMap[imageStoragePoolLockID] = make(chan bool)
		lxdStorageMapLock.Unlock()

		var imgerr error
		if !shared.PathExists(imageMntPoint) || !isBtrfsSubVolume(imageMntPoint) {
			imgerr = s.ImageCreate(fingerprint, tracker)
		}

		lxdStorageMapLock.Lock()
		if waitChannel, ok := lxdStorageOngoingOperationMap[imageStoragePoolLockID]; ok {
			close(waitChannel)
			delete(lxdStorageOngoingOperationMap, imageStoragePoolLockID)
		}
		lxdStorageMapLock.Unlock()

		if imgerr != nil {
			return errors.Wrap(imgerr, "Failed to create image volume")
		}
	}

	// Create a rw snapshot at
	// ${LXD_DIR}/storage-pools/<pool>/containers/<name>
	// from the mounted ro image snapshot mounted at
	// ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint>
	containerSubvolumeName := getContainerMountPoint(container.Project(), s.pool.Name, container.Name())
	err = s.btrfsPoolVolumesSnapshot(imageMntPoint, containerSubvolumeName, false, false)
	if err != nil {
		return errors.Wrap(err, "Failed to storage pool volume snapshot")
	}

	// Create the mountpoint for the container at:
	// ${LXD_DIR}/containers/<name>
	err = createContainerMountpoint(containerSubvolumeName, container.Path(), container.IsPrivileged())
	if err != nil {
		return errors.Wrap(err, "Failed to create container mountpoint")
	}

	logger.Debugf("Created BTRFS storage volume for container \"%s\" on storage pool \"%s\"", s.volume.Name, s.pool.Name)
	err = container.TemplateApply("create")
	if err != nil {
		return errors.Wrap(err, "Failed to apply container template")
	}
	return nil
}
func ( s * storageBtrfs ) ContainerCreateFromImage ( container container , fingerprint string , tracker * ioprogress . ProgressTracker ) error { logger . Debugf ( " \" \" \" \" " , s . volume . Name , s . pool . Name ) source := s . pool . Config [ " " ] if source == " " { return fmt . Errorf ( " \" \" " ) } _ , err := s . StoragePoolMount ( ) if err != nil { return errors . Wrap ( err , " " ) } // We can only create the btrfs subvolume under the mounted storage // pool. The on-disk layout for containers on a btrfs storage pool will // thus be // ${LXD_DIR}/storage-pools/<pool>/containers/. The btrfs tool will // complain if the intermediate path does not exist, so create it if it // doesn't already. containerSubvolumePath := s . getContainerSubvolumePath ( s . pool . Name ) if ! shared . PathExists ( containerSubvolumePath ) { err := os . MkdirAll ( containerSubvolumePath , containersDirMode ) if err != nil { return errors . Wrap ( err , " " ) } } // Mountpoint of the image: // ${LXD_DIR}/images/<fingerprint> imageMntPoint := getImageMountPoint ( s . pool . Name , fingerprint ) imageStoragePoolLockID := getImageCreateLockID ( s . pool . Name , fingerprint ) lxdStorageMapLock . Lock ( ) if waitChannel , ok := lxdStorageOngoingOperationMap [ imageStoragePoolLockID ] ; ok { lxdStorageMapLock . Unlock ( ) if _ , ok := <- waitChannel ; ok { logger . Warnf ( " " ) } } else { lxdStorageOngoingOperationMap [ imageStoragePoolLockID ] = make ( chan bool ) lxdStorageMapLock . Unlock ( ) var imgerr error if ! shared . PathExists ( imageMntPoint ) || ! isBtrfsSubVolume ( imageMntPoint ) { imgerr = s . ImageCreate ( fingerprint , tracker ) } lxdStorageMapLock . Lock ( ) if waitChannel , ok := lxdStorageOngoingOperationMap [ imageStoragePoolLockID ] ; ok { close ( waitChannel ) delete ( lxdStorageOngoingOperationMap , imageStoragePoolLockID ) } lxdStorageMapLock . Unlock ( ) if imgerr != nil { return errors . Wrap ( imgerr , " " ) } } // Create a rw snapshot at // ${LXD_DIR}/storage-pools/<pool>/containers/<name> // from the mounted ro image snapshot mounted at // ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint> containerSubvolumeName := getContainerMountPoint ( container . Project ( ) , s . pool . Name , container . Name ( ) ) err = s . btrfsPoolVolumesSnapshot ( imageMntPoint , containerSubvolumeName , false , false ) if err != nil { return errors . Wrap ( err , " " ) } // Create the mountpoint for the container at: // ${LXD_DIR}/containers/<name> err = createContainerMountpoint ( containerSubvolumeName , container . Path ( ) , container . IsPrivileged ( ) ) if err != nil { return errors . Wrap ( err , " " ) } logger . Debugf ( " \" \" \" \" " , s . volume . Name , s . pool . Name ) err = container . TemplateApply ( " " ) if err != nil { return errors . Wrap ( err , " " ) } return nil }
// And this function is why I started hating on btrfs...
And this function is why I started hating on btrfs ...