diff --git a/infoblox/provider.go b/infoblox/provider.go index 47b0d55ca..a3cfe676b 100644 --- a/infoblox/provider.go +++ b/infoblox/provider.go @@ -69,6 +69,7 @@ func Provider() terraform.ResourceProvider { "infoblox_network": resourceNetwork(), "infoblox_network_view": resourceNetworkView(), "infoblox_ip_allocation": resourceIPAllocation(), + "infoblox_ip_association": resourceIPAssociation(), }, ConfigureFunc: providerConfigure, } diff --git a/infoblox/resourceIPAllocation.go b/infoblox/resourceIPAllocation.go index d9805448d..d94be0138 100644 --- a/infoblox/resourceIPAllocation.go +++ b/infoblox/resourceIPAllocation.go @@ -21,11 +21,11 @@ func resourceIPAllocation() *schema.Resource { DefaultFunc: schema.EnvDefaultFunc("networkViewName", "default"), Description: "Network view name available in Nios server.", }, - "network_name": &schema.Schema{ + "host_name": &schema.Schema{ Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("networkName", nil), - Description: "The name of the network.", + Required: true, + DefaultFunc: schema.EnvDefaultFunc("hostName", nil), + Description: "The name of the record.", }, "cidr": &schema.Schema{ Type: schema.TypeString, @@ -42,21 +42,21 @@ func resourceIPAllocation() *schema.Resource { }, "mac_addr": &schema.Schema{ Type: schema.TypeString, - Required: true, + Optional: true, DefaultFunc: schema.EnvDefaultFunc("macaddr", nil), Description: "mac address of your instance in cloud.", }, "vm_id": &schema.Schema{ Type: schema.TypeString, - Required: true, + Optional: true, DefaultFunc: schema.EnvDefaultFunc("vmid", nil), - Description: "Virtual Machine name.", + Description: "instance name.", }, "tenant_id": &schema.Schema{ Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("tenantID", nil), - Description: "Unique identifier of your instance in cloud.", + Description: "Unique identifier of your tenant in cloud.", }, "gateway": &schema.Schema{ Type: schema.TypeString, @@ -69,10 +69,15 @@ func resourceIPAllocation() *schema.Resource { } } +//We are using creation of host record for IPAM purposes for the reason that +//if we create a fixed address,t has mac address as a required parameter and +//a mac address is not generated before provisioning of vm hence we use create +//host record method used below func resourceIPAllocationRequest(d *schema.ResourceData, m interface{}) error { log.Printf("[DEBUG] %s: Beginning to request a next free IP from a required network block", resourceIPAllocationIDString(d)) networkViewName := d.Get("network_view_name").(string) + recordName := d.Get("host_name").(string) ipAddr := d.Get("ip_addr").(string) cidr := d.Get("cidr").(string) macAddr := d.Get("mac_addr").(string) @@ -94,34 +99,31 @@ func resourceIPAllocationRequest(d *schema.ResourceData, m interface{}) error { } } - ipAddrObj, err := objMgr.AllocateIP(networkViewName, cidr, ipAddr, macAddr, vmID) + hostrecordObj, err := objMgr.CreateHostRecordWithoutDNS(recordName, networkViewName, cidr, ipAddr, macAddr, vmID) if err != nil { return fmt.Errorf("Error allocating IP from network block(%s): %s", cidr, err) } d.Set("gateway", gatewayIP.IPAddress) - d.Set("ipAddr", ipAddrObj.IPAddress) + d.Set("ip_addr", hostrecordObj.Ipv4Addrs[0].Ipv4Addr) // TODO what happens in case of a VM have 2 network interfaces. - d.SetId(vmID) + d.SetId(hostrecordObj.Ref) - log.Printf("[DEBUG] %s:completing Request of IP from required network block", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s:completing Request of IP from required network block", resourceIPAllocationIDString(d)) return nil } func resourceIPAllocationGet(d *schema.ResourceData, m interface{}) error { - log.Printf("[DEBUG] %s:Reading the required IP from network block", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s:Reading the required IP from network block", resourceIPAllocationIDString(d)) - networkViewName := d.Get("network_view_name").(string) tenantID := d.Get("tenant_id").(string) - ipAddr := d.Get("ip_addr").(string) cidr := d.Get("cidr").(string) - macAddr := d.Get("mac_addr").(string) connector := m.(*ibclient.Connector) objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) - _, err := objMgr.GetFixedAddress(networkViewName, cidr, ipAddr, macAddr) + _, err := objMgr.GetHostRecord(d.Id()) if err != nil { return fmt.Errorf("Error getting IP from network block(%s): %s", cidr, err) } @@ -132,55 +134,39 @@ func resourceIPAllocationGet(d *schema.ResourceData, m interface{}) error { func resourceIPAllocationUpdate(d *schema.ResourceData, m interface{}) error { - log.Printf("[DEBUG] %s: Updating the Parameters of the allocated IP", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s: Updating the Parameters of the allocated IP in the specified network block", resourceIPAllocationIDString(d)) - networkViewName := d.Get("network_view_ame").(string) - networkName := d.Get("network_name").(string) - ipAddr := d.Get("ip_addr").(string) - cidr := d.Get("cidr").(string) macAddr := d.Get("mac_addr").(string) - vmID := d.Get("vm_id").(string) tenantID := d.Get("tenant_id").(string) - + vmID := d.Get("vm_id").(string) connector := m.(*ibclient.Connector) objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) - ref, err := objMgr.GetFixedAddress(networkViewName, networkName, ipAddr, "") - if err != nil { - return fmt.Errorf("GetFixedAddress error from network(%s):%s", cidr, err) - } - - _, err = objMgr.UpdateFixedAddress(ref.Ref, macAddr, vmID) - if err != nil { - return fmt.Errorf("UpdateFixedAddress error from network block(%s):%s", cidr, err) - } + hostRecordObj, _ := objMgr.GetHostRecord(d.Id()) + IPAddrObj, _ := objMgr.GetIpAddressFromHostRecord(*hostRecordObj) + objMgr.UpdateHostRecordWithoutDNS(d.Id(), IPAddrObj, macAddr, vmID) - log.Printf("[DEBUG] %s: Updation of Parameters of allocated IP complete", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s: Updation of Parameters of allocated IP complete in the specified network block", resourceIPAllocationIDString(d)) return nil } func resourceIPAllocationRelease(d *schema.ResourceData, m interface{}) error { - log.Printf("[DEBUG] %s: Beginning Release of an allocated IP", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s: Beginning Release of an allocated IP in the specified network block", resourceIPAllocationIDString(d)) - networkViewName := d.Get("network_view_name").(string) - ipAddr := d.Get("ip_addr").(string) - cidr := d.Get("cidr").(string) - macAddr := d.Get("mac_addr").(string) tenantID := d.Get("tenant_id").(string) connector := m.(*ibclient.Connector) objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) - - _, err := objMgr.ReleaseIP(networkViewName, cidr, ipAddr, macAddr) + _, err := objMgr.DeleteHostRecord(d.Id()) if err != nil { - return fmt.Errorf("Error Releasing IP from network(%s): %s", cidr, err) + return fmt.Errorf("Error Releasing IP from network block having reference (%s): %s", d.Id(), err) } d.SetId("") - log.Printf("[DEBUG] %s: Finishing Release of allocated IP", resourceIPAllocationIDString(d)) + log.Printf("[DEBUG] %s: Finishing Release of allocated IP in the specified network block", resourceIPAllocationIDString(d)) return nil } diff --git a/infoblox/resourceIPAssociation.go b/infoblox/resourceIPAssociation.go new file mode 100644 index 000000000..040b23c28 --- /dev/null +++ b/infoblox/resourceIPAssociation.go @@ -0,0 +1,142 @@ +package infoblox + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "github.com/infobloxopen/infoblox-go-client" + "log" +) + +func resourceIPAssociation() *schema.Resource { + return &schema.Resource{ + Create: resourceIPAssociationCreate, + Update: resourceIPAssociationUpdate, + Delete: resourceIPAssociationDelete, + Read: resourceIPAssociationRead, + + Schema: map[string]*schema.Schema{ + "network_view_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("network_view_name", "default"), + Description: "Network view name available in Nios server.", + }, + "host_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("host_name", nil), + Description: "The name of the record.", + }, + "cidr": &schema.Schema{ + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("net_address", nil), + Description: "Give the address in cidr format.", + }, + "ip_addr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("ipaddr", nil), + Description: "IP address of your instance in cloud.", + Computed: true, + }, + "mac_addr": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("macaddr", nil), + Description: "mac address of your instance in cloud.", + }, + "vm_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("vmid", nil), + Description: "instance name.", + }, + "tenant_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("tenant_id", nil), + Description: "Unique identifier of your tenant in cloud.", + }, + }, + } +} + +//This method has an update call for the reason that,we are creating +//a host record which doesnt have the details of the mac address +//at the beginigand we are using this update call to update the mac address +//of the record after the VM has been provisined.It is in the create method +//because for this resource we are doing association instead of allocation. +func resourceIPAssociationCreate(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] %s: Beginning Association of IP address in specified network block", resourceIPAssociationIDString(d)) + + networkViewName := d.Get("network_view_name").(string) + recordName := d.Get("host_name").(string) + ipAddr := d.Get("ip_addr").(string) + cidr := d.Get("cidr").(string) + macAddr := d.Get("mac_addr").(string) + tenantID := d.Get("tenant_id").(string) + vmID := d.Get("vm_id").(string) + + connector := m.(*ibclient.Connector) + + objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) + + hostRecordObj, err := objMgr.GetHostRecordtWithoutDNS(recordName, networkViewName, cidr, ipAddr) + if err != nil { + return fmt.Errorf("GetHostAddress error from network block(%s):%s", cidr, err) + } + _, err = objMgr.UpdateHostRecordWithoutDNS(hostRecordObj.Ref, ipAddr, macAddr, vmID) + if err != nil { + return fmt.Errorf("UpdateHostAddress error from network block(%s):%s", cidr, err) + } + + d.SetId(hostRecordObj.Ref) + log.Printf("[DEBUG] %s:completing Association of IP address in specified network block", resourceIPAssociationIDString(d)) + return nil +} + +func resourceIPAssociationUpdate(d *schema.ResourceData, m interface{}) error { + return nil +} + +func resourceIPAssociationRead(d *schema.ResourceData, m interface{}) error { + return nil +} + +//we are updating the record with an empty mac address after the vm has been +//destroyed because if we implement the delete hostrecord method here then there +//will be a conflict of resources +func resourceIPAssociationDelete(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] %s: Beginning Reassociation of IP address in specified network block", resourceIPAssociationIDString(d)) + + ipAddr := d.Get("ip_addr").(string) + tenantID := d.Get("tenant_id").(string) + + connector := m.(*ibclient.Connector) + + objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) + + _, err := objMgr.UpdateHostRecordWithoutDNS(d.Id(), ipAddr, "00:00:00:00:00:00", "") + if err != nil { + return fmt.Errorf("Error Releasing IP from network block having reference (%s): %s", d.Id(), err) + } + + d.SetId("") + + log.Printf("[DEBUG] %s: Finishing Release of allocated IP in specified network block", resourceIPAssociationIDString(d)) + + return nil +} + +type resourceIPAssociationIDStringInterface interface { + Id() string +} + +func resourceIPAssociationIDString(d resourceIPAssociationIDStringInterface) string { + id := d.Id() + if id == "" { + id = "" + } + return fmt.Sprintf("infoblox_mac_allocation (ID = %s)", id) +} diff --git a/infoblox/resourceNetwork.go b/infoblox/resourceNetwork.go index a4ebbce47..4aee2fb2f 100644 --- a/infoblox/resourceNetwork.go +++ b/infoblox/resourceNetwork.go @@ -25,19 +25,19 @@ func resourceNetwork() *schema.Resource { Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("networkName", nil), - Description: "The name of the network.", + Description: "The name of your network block.", }, "cidr": &schema.Schema{ Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("net_address", nil), - Description: "Give the address in cidr format.", + Description: "Give the network block in cidr format.", }, "tenant_id": &schema.Schema{ Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("tenantID", nil), - Description: "Unique identifier of your instance in cloud.", + Description: "Unique identifier of your tenant in cloud.", }, }, } @@ -56,9 +56,9 @@ func resourceNetworkCreate(d *schema.ResourceData, m interface{}) error { nwname, err := objMgr.CreateNetwork(networkViewName, cidr, networkName) if err != nil { - return fmt.Errorf("Creation of network failed in network view (%s) : %s", networkViewName, err) + return fmt.Errorf("Creation of network block failed in network view (%s) : %s", networkViewName, err) } - d.SetId(nwname.Cidr) + d.SetId(nwname.Ref) log.Printf("[DEBUG] %s: Creation on network block complete", resourceNetworkIDString(d)) return nil @@ -67,15 +67,14 @@ func resourceNetworkRead(d *schema.ResourceData, m interface{}) error { log.Printf("[DEBUG] %s: Reading the required network block", resourceNetworkIDString(d)) networkViewName := d.Get("network_view_name").(string) - cidr := d.Get("cidr").(string) tenantID := d.Get("tenant_id").(string) connector := m.(*ibclient.Connector) objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) - _, err := objMgr.GetNetwork(networkViewName, cidr, nil) + _, err := objMgr.GetNetworkwithref(d.Id()) if err != nil { - return fmt.Errorf("Getting Network from network view (%s) failed : %s", networkViewName, err) + return fmt.Errorf("Getting Network block from network view (%s) failed : %s", networkViewName, err) } log.Printf("[DEBUG] %s: Completed reading network block", resourceNetworkIDString(d)) @@ -90,20 +89,14 @@ func resourceNetworkDelete(d *schema.ResourceData, m interface{}) error { log.Printf("[DEBUG] %s: Beginning Deletion of network block", resourceNetworkIDString(d)) networkViewName := d.Get("network_view_name").(string) - cidr := d.Get("cidr").(string) tenantID := d.Get("tenant_id").(string) connector := m.(*ibclient.Connector) objMgr := ibclient.NewObjectManager(connector, "terraform", tenantID) - ref, err := objMgr.GetNetwork(networkViewName, cidr, nil) - if err != nil { - return fmt.Errorf("Getting Network failed from network view(%s) for deletion : %s", networkViewName, err) - } - - _, err = objMgr.DeleteNetwork(ref.Ref, d.Get("network_view_name").(string)) + _, err := objMgr.DeleteNetwork(d.Id(), d.Get("network_view_name").(string)) if err != nil { - return fmt.Errorf("Deletion of Network failed from network view(%s) for deletion : %s", networkViewName, err) + return fmt.Errorf("Deletion of Network block failed from network view(%s) for deletion : %s", networkViewName, err) } d.SetId("") diff --git a/infoblox/resourceNetworkView.go b/infoblox/resourceNetworkView.go index 268888351..970d94dce 100644 --- a/infoblox/resourceNetworkView.go +++ b/infoblox/resourceNetworkView.go @@ -25,7 +25,7 @@ func resourceNetworkView() *schema.Resource { Type: schema.TypeString, Required: true, DefaultFunc: schema.EnvDefaultFunc("tennant_id", nil), - Description: "Unique identifier of your instace in cloud.", + Description: "Unique identifier of your tenant in cloud.", }, }, } @@ -86,5 +86,5 @@ func resourceNetworkViewIDString(d resourceNetworkViewIDStringInterface) string if id == "" { id = "" } - return fmt.Sprintf("infoblox_ip_allocation (ID = %s)", id) + return fmt.Sprintf("infoblox_network(ID = %s)", id) }