lxd/api_cluster.go
func clusterInitMember(d, client lxd.ContainerServer, memberConfig []api.ClusterMemberConfigKey) error {
	data := initDataNode{}

	// Fetch all pools currently defined in the cluster.
	pools, err := client.GetStoragePools()
	if err != nil {
		return errors.Wrap(err, "Failed to fetch information about cluster storage pools")
	}

	// Merge the returned storage pools configs with the node-specific
	// configs provided by the user.
	for _, pool := range pools {
		// Skip pending pools.
		if pool.Status == "Pending" {
			continue
		}

		// Skip ceph pools since they have no node-specific key and
		// don't need to be defined on joining nodes.
		if pool.Driver == "ceph" {
			continue
		}

		logger.Debugf("Populating init data for storage pool %s", pool.Name)

		post := api.StoragePoolsPost{
			StoragePoolPut: pool.StoragePoolPut,
			Driver:         pool.Driver,
			Name:           pool.Name,
		}

		// Delete config keys that are automatically populated by LXD
		delete(post.Config, "volatile.initial_source")
		delete(post.Config, "zfs.pool_name")

		// Apply the node-specific config supplied by the user.
		for _, config := range memberConfig {
			if config.Entity != "storage-pool" {
				continue
			}

			if config.Name != pool.Name {
				continue
			}

			if !shared.StringInSlice(config.Key, db.StoragePoolNodeConfigKeys) {
				logger.Warnf("Ignoring config key %s for storage pool %s", config.Key, config.Name)
				continue
			}

			post.Config[config.Key] = config.Value
		}

		data.StoragePools = append(data.StoragePools, post)
	}

	// Fetch all networks currently defined in the cluster.
	networks, err := client.GetNetworks()
	if err != nil {
		return errors.Wrap(err, "Failed to fetch information about cluster networks")
	}

	// Merge the returned storage networks configs with the node-specific
	// configs provided by the user.
	for _, network := range networks {
		// Skip not-managed or pending networks
		if !network.Managed || network.Status == "Pending" {
			continue
		}

		post := api.NetworksPost{
			NetworkPut: network.NetworkPut,
			Managed:    true,
			Name:       network.Name,
			Type:       network.Type,
		}

		// Apply the node-specific config supplied by the user.
		for _, config := range memberConfig {
			if config.Entity != "network" {
				continue
			}

			if config.Name != network.Name {
				continue
			}

			if !shared.StringInSlice(config.Key, db.NetworkNodeConfigKeys) {
				logger.Warnf("Ignoring config key %s for network %s", config.Key, config.Name)
				continue
			}

			post.Config[config.Key] = config.Value
		}

		data.Networks = append(data.Networks, post)
	}

	revert, err := initDataNodeApply(d, data)
	if err != nil {
		revert()
		return errors.Wrap(err, "Failed to initialize storage pools and networks")
	}

	return nil
}
func clusterInitMember(d, client lxd.ContainerServer, memberConfig []api.ClusterMemberConfigKey) error {
	data := initDataNode{}

	// Fetch all pools currently defined in the cluster.
	pools, err := client.GetStoragePools()
	if err != nil {
		return errors.Wrap(err, "Failed to fetch information about cluster storage pools")
	}

	// Merge the returned storage pools configs with the node-specific
	// configs provided by the user.
	for _, pool := range pools {
		// Skip pending pools.
		if pool.Status == "Pending" {
			continue
		}

		// Skip ceph pools since they have no node-specific key and
		// don't need to be defined on joining nodes.
		if pool.Driver == "ceph" {
			continue
		}

		logger.Debugf("Populating init data for storage pool %s", pool.Name)

		post := api.StoragePoolsPost{
			StoragePoolPut: pool.StoragePoolPut,
			Driver:         pool.Driver,
			Name:           pool.Name,
		}

		// Delete config keys that are automatically populated by LXD
		delete(post.Config, "volatile.initial_source")
		delete(post.Config, "zfs.pool_name")

		// Apply the node-specific config supplied by the user.
		for _, config := range memberConfig {
			if config.Entity != "storage-pool" {
				continue
			}

			if config.Name != pool.Name {
				continue
			}

			if !shared.StringInSlice(config.Key, db.StoragePoolNodeConfigKeys) {
				logger.Warnf("Ignoring config key %s for storage pool %s", config.Key, config.Name)
				continue
			}

			post.Config[config.Key] = config.Value
		}

		data.StoragePools = append(data.StoragePools, post)
	}

	// Fetch all networks currently defined in the cluster.
	networks, err := client.GetNetworks()
	if err != nil {
		return errors.Wrap(err, "Failed to fetch information about cluster networks")
	}

	// Merge the returned storage networks configs with the node-specific
	// configs provided by the user.
	for _, network := range networks {
		// Skip not-managed or pending networks
		if !network.Managed || network.Status == "Pending" {
			continue
		}

		post := api.NetworksPost{
			NetworkPut: network.NetworkPut,
			Managed:    true,
			Name:       network.Name,
			Type:       network.Type,
		}

		// Apply the node-specific config supplied by the user.
		for _, config := range memberConfig {
			if config.Entity != "network" {
				continue
			}

			if config.Name != network.Name {
				continue
			}

			if !shared.StringInSlice(config.Key, db.NetworkNodeConfigKeys) {
				logger.Warnf("Ignoring config key %s for network %s", config.Key, config.Name)
				continue
			}

			post.Config[config.Key] = config.Value
		}

		data.Networks = append(data.Networks, post)
	}

	revert, err := initDataNodeApply(d, data)
	if err != nil {
		revert()
		return errors.Wrap(err, "Failed to initialize storage pools and networks")
	}

	return nil
}
func clusterInitMember ( d , client lxd . ContainerServer , memberConfig [ ] api . ClusterMemberConfigKey ) error { data := initDataNode { } // Fetch all pools currently defined in the cluster. pools , err := client . GetStoragePools ( ) if err != nil { return errors . Wrap ( err , " " ) } // Merge the returned storage pools configs with the node-specific // configs provided by the user. for _ , pool := range pools { // Skip pending pools. if pool . Status == " " { continue } // Skip ceph pools since they have no node-specific key and // don't need to be defined on joining nodes. if pool . Driver == " " { continue } logger . Debugf ( " " , pool . Name ) post := api . StoragePoolsPost { StoragePoolPut : pool . StoragePoolPut , Driver : pool . Driver , Name : pool . Name , } // Delete config keys that are automatically populated by LXD delete ( post . Config , " " ) delete ( post . Config , " " ) // Apply the node-specific config supplied by the user. for _ , config := range memberConfig { if config . Entity != " " { continue } if config . Name != pool . Name { continue } if ! shared . StringInSlice ( config . Key , db . StoragePoolNodeConfigKeys ) { logger . Warnf ( " " , config . Key , config . Name ) continue } post . Config [ config . Key ] = config . Value } data . StoragePools = append ( data . StoragePools , post ) } // Fetch all networks currently defined in the cluster. networks , err := client . GetNetworks ( ) if err != nil { return errors . Wrap ( err , " " ) } // Merge the returned storage networks configs with the node-specific // configs provided by the user. for _ , network := range networks { // Skip not-managed or pending networks if ! network . Managed || network . Status == " " { continue } post := api . NetworksPost { NetworkPut : network . NetworkPut , Managed : true , Name : network . Name , Type : network . Type , } // Apply the node-specific config supplied by the user. for _ , config := range memberConfig { if config . Entity != " " { continue } if config . Name != network . Name { continue } if ! shared . StringInSlice ( config . Key , db . NetworkNodeConfigKeys ) { logger . Warnf ( " " , config . Key , config . Name ) continue } post . Config [ config . Key ] = config . Value } data . Networks = append ( data . Networks , post ) } revert , err := initDataNodeApply ( d , data ) if err != nil { revert ( ) return errors . Wrap ( err , " " ) } return nil }
// Initialize storage pools and networks on this node.
//
// We pass to LXD client instances, one connected to ourselves (the joining
// node) and one connected to the target cluster node to join.
Initialize storage pools and networks on this node . We pass to LXD client instances one connected to ourselves ( the joining node ) and one connected to the target cluster node to join .