func storagePoolsPost(d *Daemon, r *http.Request) Response {
	storagePoolCreateLock.Lock()
	defer storagePoolCreateLock.Unlock()

	req := api.StoragePoolsPost{}

	// Parse the request.
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		return BadRequest(err)
	}

	// Sanity checks.
	if req.Name == "" {
		return BadRequest(fmt.Errorf("No name provided"))
	}

	if strings.Contains(req.Name, "/") {
		return BadRequest(fmt.Errorf("Storage pool names may not contain slashes"))
	}

	if req.Driver == "" {
		return BadRequest(fmt.Errorf("No driver provided"))
	}

	url := fmt.Sprintf("/%s/storage-pools/%s", version.APIVersion, req.Name)
	response := SyncResponseLocation(true, nil, url)

	if isClusterNotification(r) {
		// This is an internal request which triggers the actual
		// creation of the pool across all nodes, after they have been
		// previously defined.
		err = storagePoolValidate(req.Name, req.Driver, req.Config)
		if err != nil {
			return BadRequest(err)
		}
		err = doStoragePoolCreateInternal(
			d.State(), req.Name, req.Description, req.Driver, req.Config, true)
		if err != nil {
			return SmartError(err)
		}
		return response
	}

	targetNode := queryParam(r, "target")
	if targetNode == "" {
		count, err := cluster.Count(d.State())
		if err != nil {
			return SmartError(err)
		}

		if count == 1 {
			// No targetNode was specified and we're either a single-node
			// cluster or not clustered at all, so create the storage
			// pool immediately.
			err = storagePoolCreateInternal(
				d.State(), req.Name, req.Description, req.Driver, req.Config)
		} else {
			// No targetNode was specified and we're clustered, so finalize the
			// config in the db and actually create the pool on all nodes.
			err = storagePoolsPostCluster(d, req)
		}
		if err != nil {
			return InternalError(err)
		}
		return response

	}

	// A targetNode was specified, let's just define the node's storage
	// without actually creating it. The only legal key values for the
	// storage config are the ones in StoragePoolNodeConfigKeys.
	for key := range req.Config {
		if !shared.StringInSlice(key, db.StoragePoolNodeConfigKeys) {
			return SmartError(fmt.Errorf("Config key '%s' may not be used as node-specific key", key))
		}
	}

	err = storagePoolValidate(req.Name, req.Driver, req.Config)
	if err != nil {
		return BadRequest(err)
	}

	err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
		return tx.StoragePoolCreatePending(targetNode, req.Name, req.Driver, req.Config)
	})
	if err != nil {
		if err == db.ErrAlreadyDefined {
			return BadRequest(fmt.Errorf("The storage pool already defined on node %s", targetNode))
		}
		return SmartError(err)
	}

	return response
}
func storagePoolsPost(d *Daemon, r *http.Request) Response {
	storagePoolCreateLock.Lock()
	defer storagePoolCreateLock.Unlock()

	req := api.StoragePoolsPost{}

	
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		return BadRequest(err)
	}

	
	if req.Name == "" {
		return BadRequest(fmt.Errorf("No name provided"))
	}

	if strings.Contains(req.Name, "/") {
		return BadRequest(fmt.Errorf("Storage pool names may not contain slashes"))
	}

	if req.Driver == "" {
		return BadRequest(fmt.Errorf("No driver provided"))
	}

	url := fmt.Sprintf("/%s/storage-pools/%s", version.APIVersion, req.Name)
	response := SyncResponseLocation(true, nil, url)

	if isClusterNotification(r) {
		
		
		
		err = storagePoolValidate(req.Name, req.Driver, req.Config)
		if err != nil {
			return BadRequest(err)
		}
		err = doStoragePoolCreateInternal(
			d.State(), req.Name, req.Description, req.Driver, req.Config, true)
		if err != nil {
			return SmartError(err)
		}
		return response
	}

	targetNode := queryParam(r, "target")
	if targetNode == "" {
		count, err := cluster.Count(d.State())
		if err != nil {
			return SmartError(err)
		}

		if count == 1 {
			
			
			
			err = storagePoolCreateInternal(
				d.State(), req.Name, req.Description, req.Driver, req.Config)
		} else {
			
			
			err = storagePoolsPostCluster(d, req)
		}
		if err != nil {
			return InternalError(err)
		}
		return response

	}

	
	
	
	for key := range req.Config {
		if !shared.StringInSlice(key, db.StoragePoolNodeConfigKeys) {
			return SmartError(fmt.Errorf("Config key '%s' may not be used as node-specific key", key))
		}
	}

	err = storagePoolValidate(req.Name, req.Driver, req.Config)
	if err != nil {
		return BadRequest(err)
	}

	err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
		return tx.StoragePoolCreatePending(targetNode, req.Name, req.Driver, req.Config)
	})
	if err != nil {
		if err == db.ErrAlreadyDefined {
			return BadRequest(fmt.Errorf("The storage pool already defined on node %s", targetNode))
		}
		return SmartError(err)
	}

	return response
}
func storagePoolsPost ( d * Daemon , r * http . Request ) Response { storagePoolCreateLock . Lock ( ) defer storagePoolCreateLock . Unlock ( ) req := api . StoragePoolsPost { } // Parse the request. err := json . NewDecoder ( r . Body ) . Decode ( & req ) if err != nil { return BadRequest ( err ) } // Sanity checks. if req . Name == " " { return BadRequest ( fmt . Errorf ( " " ) ) } if strings . Contains ( req . Name , " " ) { return BadRequest ( fmt . Errorf ( " " ) ) } if req . Driver == " " { return BadRequest ( fmt . Errorf ( " " ) ) } url := fmt . Sprintf ( " " , version . APIVersion , req . Name ) response := SyncResponseLocation ( true , nil , url ) if isClusterNotification ( r ) { // This is an internal request which triggers the actual // creation of the pool across all nodes, after they have been // previously defined. err = storagePoolValidate ( req . Name , req . Driver , req . Config ) if err != nil { return BadRequest ( err ) } err = doStoragePoolCreateInternal ( d . State ( ) , req . Name , req . Description , req . Driver , req . Config , true ) if err != nil { return SmartError ( err ) } return response } targetNode := queryParam ( r , " " ) if targetNode == " " { count , err := cluster . Count ( d . State ( ) ) if err != nil { return SmartError ( err ) } if count == 1 { // No targetNode was specified and we're either a single-node // cluster or not clustered at all, so create the storage // pool immediately. err = storagePoolCreateInternal ( d . State ( ) , req . Name , req . Description , req . Driver , req . Config ) } else { // No targetNode was specified and we're clustered, so finalize the // config in the db and actually create the pool on all nodes. err = storagePoolsPostCluster ( d , req ) } if err != nil { return InternalError ( err ) } return response } // A targetNode was specified, let's just define the node's storage // without actually creating it. The only legal key values for the // storage config are the ones in StoragePoolNodeConfigKeys. for key := range req . Config { if ! shared . StringInSlice ( key , db . StoragePoolNodeConfigKeys ) { return SmartError ( fmt . Errorf ( " " , key ) ) } } err = storagePoolValidate ( req . Name , req . Driver , req . Config ) if err != nil { return BadRequest ( err ) } err = d . cluster . Transaction ( func ( tx * db . ClusterTx ) error { return tx . StoragePoolCreatePending ( targetNode , req . Name , req . Driver , req . Config ) } ) if err != nil { if err == db . ErrAlreadyDefined { return BadRequest ( fmt . Errorf ( " " , targetNode ) ) } return SmartError ( err ) } return response }
// /1.0/storage-pools
// Create a storage pool.
/ 1 . 0 / storage - pools Create a storage pool .