func listNodesHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	pools, err := permission.ListContextValues(t, permission.PermNodeRead, false)
	if err != nil {
		return err
	}
	provs, err := provision.Registry()
	if err != nil {
		return err
	}
	provNameMap := map[string]string{}
	var allNodes []provision.NodeSpec
	for _, prov := range provs {
		nodeProv, ok := prov.(provision.NodeProvisioner)
		if !ok {
			continue
		}
		var nodes []provision.Node
		nodes, err = nodeProv.ListNodes(nil)
		if err != nil {
			allNodes = append(allNodes, provision.NodeSpec{
				Address: fmt.Sprintf("%s nodes", prov.GetName()),
				Status:  fmt.Sprintf("ERROR: %v", err),
			})
			continue
		}
		for _, n := range nodes {
			provNameMap[n.Address()] = prov.GetName()
			allNodes = append(allNodes, provision.NodeToSpec(n))
		}
	}
	if pools != nil {
		filteredNodes := make([]provision.NodeSpec, 0, len(allNodes))
		for _, node := range allNodes {
			for _, pool := range pools {
				if node.Pool == pool {
					filteredNodes = append(filteredNodes, node)
					break
				}
			}
		}
		allNodes = filteredNodes
	}
	iaases, err := permission.ListContextValues(t, permission.PermMachineRead, false)
	if err != nil {
		return err
	}
	machines, err := iaas.ListMachines()
	if err != nil {
		return err
	}
	if iaases != nil {
		filteredMachines := make([]iaas.Machine, 0, len(machines))
		for _, machine := range machines {
			for _, iaas := range iaases {
				if machine.Iaas == iaas {
					filteredMachines = append(filteredMachines, machine)
					break
				}
			}
		}
		machines = filteredMachines
	}
	if len(allNodes) == 0 && len(machines) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	result := apiTypes.ListNodeResponse{
		Nodes:    allNodes,
		Machines: machines,
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(result)
}
func listNodesHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	pools, err := permission.ListContextValues(t, permission.PermNodeRead, false)
	if err != nil {
		return err
	}
	provs, err := provision.Registry()
	if err != nil {
		return err
	}
	provNameMap := map[string]string{}
	var allNodes []provision.NodeSpec
	for _, prov := range provs {
		nodeProv, ok := prov.(provision.NodeProvisioner)
		if !ok {
			continue
		}
		var nodes []provision.Node
		nodes, err = nodeProv.ListNodes(nil)
		if err != nil {
			allNodes = append(allNodes, provision.NodeSpec{
				Address: fmt.Sprintf("%s nodes", prov.GetName()),
				Status:  fmt.Sprintf("ERROR: %v", err),
			})
			continue
		}
		for _, n := range nodes {
			provNameMap[n.Address()] = prov.GetName()
			allNodes = append(allNodes, provision.NodeToSpec(n))
		}
	}
	if pools != nil {
		filteredNodes := make([]provision.NodeSpec, 0, len(allNodes))
		for _, node := range allNodes {
			for _, pool := range pools {
				if node.Pool == pool {
					filteredNodes = append(filteredNodes, node)
					break
				}
			}
		}
		allNodes = filteredNodes
	}
	iaases, err := permission.ListContextValues(t, permission.PermMachineRead, false)
	if err != nil {
		return err
	}
	machines, err := iaas.ListMachines()
	if err != nil {
		return err
	}
	if iaases != nil {
		filteredMachines := make([]iaas.Machine, 0, len(machines))
		for _, machine := range machines {
			for _, iaas := range iaases {
				if machine.Iaas == iaas {
					filteredMachines = append(filteredMachines, machine)
					break
				}
			}
		}
		machines = filteredMachines
	}
	if len(allNodes) == 0 && len(machines) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	result := apiTypes.ListNodeResponse{
		Nodes:    allNodes,
		Machines: machines,
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(result)
}
// title: list nodes
// path: /{provisioner}/node
// method: GET
// produce: application/json
// responses:
//   200: Ok
//   204: No content