Skip to content

Commit

Permalink
Add support for allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
stbenjam committed Apr 9, 2019
1 parent 10e4860 commit 2fb3ecd
Show file tree
Hide file tree
Showing 7,502 changed files with 211,061 additions and 1,095,605 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
605 changes: 605 additions & 0 deletions Gopkg.lock

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
branch = "master"
name = "github.com/gophercloud/gophercloud"

[[constraint]]
branch = "master"
name = "github.com/gophercloud/utils"

[[constraint]]
name = "github.com/hashicorp/terraform"
version = "0.11.13"

[prune]
go-tests = true
unused-packages = true
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ endif
default: fmt lint build

build:
go build -ldflags "${LDFLAGS}"
go build -ldflags "${LDFLAGS}" -tags "${TAGS}"

install: default
mkdir -p ${TERRAFORM_PLUGINS}
Expand All @@ -27,10 +27,10 @@ lint: tools
go run golang.org/x/lint/golint -set_exit_status ./ironic .

test:
go test -v ./ironic
go test -tags "${TAGS}" -v ./ironic

acceptance:
TF_ACC=true go test -v ./ironic/...
TF_ACC=true go test -tags "acceptance" -v ./ironic/...

clean:
rm -f terraform-provider-ironic
Expand Down
58 changes: 54 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,29 @@

This is a terraform provider that lets you provision baremetal servers managed by Ironic.

# Usage
## Provider

Example:
Currently the provider only supports standalone noauth Ironic. At a
minimum, the Ironic endpoint URL must be specified. The user may also
optionally specify an API microversion.

```terraform
provider "ironic" {
"url" = "http://localhost:6385/v1"
"microversion" = "1.50"
url = "http://localhost:6385/v1"
microversion = "1.52"
}
```

## Resources

This provider currently implements a number of native Ironic resources,
described below.

### Nodes

A node describes a hardware resource.

```terraform
resource "ironic_node_v1" "openshift-master-0" {
name = "openshift-master-0"
target_provision_state = "active"
Expand Down Expand Up @@ -50,6 +63,43 @@ resource "ironic_node_v1" "openshift-master-0" {
}
```

## Ports

Ports may be specified as part of the node resource, or as a separate `ironic_port_v1`
declaration.

```terraform
resource "ironic_port_v1" "openshift-master-0-port-0" {
node_uuid = "${ironic_node_v1.openshift-master-0.id}"
pxe_enabled = true
address = "00:bb:4a:d0:5e:38"
}
```

## Allocation

The Allocation resource represents a request to find and allocate a Node
for deployment. The microversion must be 1.52 or later.

```terraform
resource "ironic_allocation_v1" "openshift-master-allocation" {
name = "master-${count.index}"
count = 3
resource_class = "baremetal"
candidates = [
"${ironic_node_v1.openshift-master-0.id}",
"${ironic_node_v1.openshift-master-1.id}",
"${ironic_node_v1.openshift-master-2.id}",
]
traits = [
"CUSTOM_FOO",
]
}
```

# License

Apache 2.0, See LICENSE file
22 changes: 0 additions & 22 deletions glide.lock

This file was deleted.

15 changes: 0 additions & 15 deletions glide.yaml

This file was deleted.

7 changes: 4 additions & 3 deletions ironic/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ func Provider() terraform.ResourceProvider {
"microversion": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("IRONIC_MICROVERSION", "1.50"),
DefaultFunc: schema.EnvDefaultFunc("IRONIC_MICROVERSION", "1.52"),
Description: descriptions["microversion"],
},
},
ResourcesMap: map[string]*schema.Resource{
"ironic_node_v1": resourceNodeV1(),
"ironic_port_v1": resourcePortV1(),
"ironic_node_v1": resourceNodeV1(),
"ironic_port_v1": resourcePortV1(),
"ironic_allocation_v1": resourceAllocationV1(),
},
ConfigureFunc: configureProvider,
}
Expand Down
2 changes: 2 additions & 0 deletions ironic/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build acceptance

package ironic

import (
Expand Down
160 changes: 160 additions & 0 deletions ironic/resource_ironic_allocation_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package ironic

import (
"fmt"
"log"
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations"
"github.com/hashicorp/terraform/helper/schema"
)

// Schema resource definition for an Ironic allocation.
func resourceAllocationV1() *schema.Resource {
return &schema.Resource{
Create: resourceAllocationV1Create,
Read: resourceAllocationV1Read,
Delete: resourceAllocationV1Delete,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"resource_class": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"candidate_nodes": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
ForceNew: true,
},
"traits": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
ForceNew: true,
},
"extra": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
"node_uuid": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
"last_error": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

// Create an allocation, including driving Ironic's state machine
func resourceAllocationV1Create(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gophercloud.ServiceClient)

result, err := allocations.Create(client, allocationSchemaToCreateOpts(d)).Extract()
if err != nil {
return err
}

d.SetId(result.UUID)

// Wait for state to change from allocating
var state string
timeout := 1 * time.Minute
checkInterval := 5 * time.Second


for resourceAllocationV1Read(d, meta) ; state == "allocating" || state == ""; resourceAllocationV1Read(d, meta) {
state = d.Get("state").(string)
log.Printf("[DEBUG] Requested allocation %s; current state is '%s'\n", d.Id(), state)

time.Sleep(checkInterval)
timeout -= checkInterval
if timeout < 0 {
return fmt.Errorf("timed out waiting for allocation")
}
}

if state == "error" {
err := d.Get("last_error").(string)
resourceAllocationV1Delete(d, meta)
d.SetId("")
return fmt.Errorf("error creating resource: %s", err)
}

return nil
}

// Read the allocation's data from Ironic
func resourceAllocationV1Read(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gophercloud.ServiceClient)

result, err := allocations.Get(client, d.Id()).Extract()
if err != nil {
return err
}

d.Set("name", result.Name)
d.Set("resource_class", result.ResourceClass)
d.Set("candidate_nodes", result.CandidateNodes)
d.Set("traits", result.Traits)
d.Set("extra", result.Extra)
d.Set("node_uuid", result.NodeUUID)
d.Set("state", result.State)
d.Set("last_error", result.LastError)

return nil
}

// Delete an allocation from Ironic
func resourceAllocationV1Delete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gophercloud.ServiceClient)
return allocations.Delete(client, d.Id()).ExtractErr()
}

func allocationSchemaToCreateOpts(d *schema.ResourceData) *allocations.CreateOpts {
candidateNodesRaw := d.Get("candidate_nodes").([]interface{})
traitsRaw := d.Get("traits").([]interface{})
extraRaw := d.Get("extra").(map[string]interface{})

candidateNodes := make([]string, len(candidateNodesRaw))
for i := range candidateNodesRaw {
candidateNodes[i] = candidateNodesRaw[i].(string)
}

traits := make([]string, len(traitsRaw))
for i := range traitsRaw {
traits[i] = traitsRaw[i].(string)
}

extra := make(map[string]string)
for k, v := range extraRaw {
extra[k] = v.(string)
}

return &allocations.CreateOpts{
Name: d.Get("name").(string),
ResourceClass: d.Get("resource_class").(string),
CandidateNodes: candidateNodes,
Traits: traits,
Extra: extra,
}
}
Loading

0 comments on commit 2fb3ecd

Please sign in to comment.