lxd/db/node.go
func (c *ClusterTx) NodeIsEmpty(id int64) (string, error) {
	// Check if the node has any containers.
	containers, err := query.SelectStrings(c.tx, "SELECT name FROM containers WHERE node_id=?", id)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get containers for node %d", id)
	}
	if len(containers) > 0 {
		message := fmt.Sprintf(
			"Node still has the following containers: %s", strings.Join(containers, ", "))
		return message, nil
	}

	// Check if the node has any images available only in it.
	images := []struct {
		fingerprint string
		nodeID      int64
	}{}
	dest := func(i int) []interface{} {
		images = append(images, struct {
			fingerprint string
			nodeID      int64
		}{})
		return []interface{}{&images[i].fingerprint, &images[i].nodeID}

	}
	stmt, err := c.tx.Prepare(`
SELECT fingerprint, node_id FROM images JOIN images_nodes ON images.id=images_nodes.image_id`)
	if err != nil {
		return "", err
	}
	defer stmt.Close()
	err = query.SelectObjects(stmt, dest)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get image list for node %d", id)
	}
	index := map[string][]int64{} // Map fingerprints to IDs of nodes
	for _, image := range images {
		index[image.fingerprint] = append(index[image.fingerprint], image.nodeID)
	}

	fingerprints := []string{}
	for fingerprint, ids := range index {
		if len(ids) > 1 {
			continue
		}
		if ids[0] == id {
			fingerprints = append(fingerprints, fingerprint)
		}
	}

	if len(fingerprints) > 0 {
		message := fmt.Sprintf(
			"Node still has the following images: %s", strings.Join(fingerprints, ", "))
		return message, nil
	}

	// Check if the node has any custom volumes.
	volumes, err := query.SelectStrings(
		c.tx, "SELECT name FROM storage_volumes WHERE node_id=? AND type=?",
		id, StoragePoolVolumeTypeCustom)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get custom volumes for node %d", id)
	}
	if len(volumes) > 0 {
		message := fmt.Sprintf(
			"Node still has the following custom volumes: %s", strings.Join(volumes, ", "))
		return message, nil
	}

	return "", nil
}
func (c *ClusterTx) NodeIsEmpty(id int64) (string, error) {
	// Check if the node has any containers.
	containers, err := query.SelectStrings(c.tx, "SELECT name FROM containers WHERE node_id=?", id)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get containers for node %d", id)
	}
	if len(containers) > 0 {
		message := fmt.Sprintf(
			"Node still has the following containers: %s", strings.Join(containers, ", "))
		return message, nil
	}

	// Check if the node has any images available only in it.
	images := []struct {
		fingerprint string
		nodeID      int64
	}{}
	dest := func(i int) []interface{} {
		images = append(images, struct {
			fingerprint string
			nodeID      int64
		}{})
		return []interface{}{&images[i].fingerprint, &images[i].nodeID}

	}
	stmt, err := c.tx.Prepare(`
SELECT fingerprint, node_id FROM images JOIN images_nodes ON images.id=images_nodes.image_id`)
	if err != nil {
		return "", err
	}
	defer stmt.Close()
	err = query.SelectObjects(stmt, dest)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get image list for node %d", id)
	}
	index := map[string][]int64{} // Map fingerprints to IDs of nodes
	for _, image := range images {
		index[image.fingerprint] = append(index[image.fingerprint], image.nodeID)
	}

	fingerprints := []string{}
	for fingerprint, ids := range index {
		if len(ids) > 1 {
			continue
		}
		if ids[0] == id {
			fingerprints = append(fingerprints, fingerprint)
		}
	}

	if len(fingerprints) > 0 {
		message := fmt.Sprintf(
			"Node still has the following images: %s", strings.Join(fingerprints, ", "))
		return message, nil
	}

	// Check if the node has any custom volumes.
	volumes, err := query.SelectStrings(
		c.tx, "SELECT name FROM storage_volumes WHERE node_id=? AND type=?",
		id, StoragePoolVolumeTypeCustom)
	if err != nil {
		return "", errors.Wrapf(err, "Failed to get custom volumes for node %d", id)
	}
	if len(volumes) > 0 {
		message := fmt.Sprintf(
			"Node still has the following custom volumes: %s", strings.Join(volumes, ", "))
		return message, nil
	}

	return "", nil
}
func ( c * ClusterTx ) NodeIsEmpty ( id int64 ) ( string , error ) { // Check if the node has any containers. containers , err := query . SelectStrings ( c . tx , " " , id ) if err != nil { return " " , errors . Wrapf ( err , " " , id ) } if len ( containers ) > 0 { message := fmt . Sprintf ( " " , strings . Join ( containers , " " ) ) return message , nil } // Check if the node has any images available only in it. images := [ ] struct { fingerprint string nodeID int64 } { } dest := func ( i int ) [ ] interface { } { images = append ( images , struct { fingerprint string nodeID int64 } { } ) return [ ] interface { } { & images [ i ] . fingerprint , & images [ i ] . nodeID } } stmt , err := c . tx . Prepare ( `
SELECT fingerprint, node_id FROM images JOIN images_nodes ON images.id=images_nodes.image_id` ) if err != nil { return " " , err } defer stmt . Close ( ) err = query . SelectObjects ( stmt , dest ) if err != nil { return " " , errors . Wrapf ( err , " " , id ) } index := map [ string ] [ ] int64 { } // Map fingerprints to IDs of nodes for _ , image := range images { index [ image . fingerprint ] = append ( index [ image . fingerprint ] , image . nodeID ) } fingerprints := [ ] string { } for fingerprint , ids := range index { if len ( ids ) > 1 { continue } if ids [ 0 ] == id { fingerprints = append ( fingerprints , fingerprint ) } } if len ( fingerprints ) > 0 { message := fmt . Sprintf ( " " , strings . Join ( fingerprints , " " ) ) return message , nil } // Check if the node has any custom volumes. volumes , err := query . SelectStrings ( c . tx , " " , id , StoragePoolVolumeTypeCustom ) if err != nil { return " " , errors . Wrapf ( err , " " , id ) } if len ( volumes ) > 0 { message := fmt . Sprintf ( " " , strings . Join ( volumes , " " ) ) return message , nil } return " " , nil }
// NodeIsEmpty returns an empty string if the node with the given ID has no
// containers or images associated with it. Otherwise, it returns a message
// say what's left.
NodeIsEmpty returns an empty string if the node with the given ID has no containers or images associated with it . Otherwise it returns a message say what s left .