This commit is contained in:
2026-06-02 11:28:16 +03:00
parent af79f6ab3e
commit c734dcfff7
254 changed files with 10439 additions and 3751 deletions

View File

@@ -14,6 +14,7 @@ func flattenLogicalPortResource(d *schema.ResourceData, logicalPort *logicalport
d.Set("description", logicalPort.Description)
d.Set("display_name", logicalPort.DisplayName)
d.Set("enabled", logicalPort.Enabled)
d.Set("external_network_id", logicalPort.ExternalNetworkID)
d.Set("hypervisor", logicalPort.Hypervisor)
d.Set("hypervisor_display_name", logicalPort.HypervisorDisplayName)
d.Set("live_migration_target_hv", logicalPort.LiveMigrationTargetHV)
@@ -21,6 +22,7 @@ func flattenLogicalPortResource(d *schema.ResourceData, logicalPort *logicalport
d.Set("unique_identifier", logicalPort.UniqueIdentifier)
d.Set("version_id", logicalPort.VersionID)
d.Set("bindings", flattenBindings(logicalPort.Bindings))
d.Set("labels", flattenLabels(logicalPort.Labels))
d.Set("created_at", logicalPort.CreatedAt)
}
@@ -38,11 +40,13 @@ func flattenLogicalPortList(lpl *logicalports.LogicalPortsList) []map[string]int
"enabled": v.Enabled,
"hypervisor": v.Hypervisor,
"hypervisor_display_name": v.HypervisorDisplayName,
"external_network_id": v.ExternalNetworkID,
"live_migration_target_hv": v.LiveMigrationTargetHV,
"status": flattenStatus(v.Status),
"unique_identifier": v.UniqueIdentifier,
"version_id": v.VersionID,
"bindings": flattenBindings(v.Bindings),
"labels": flattenLabels(v.Labels),
"created_at": v.CreatedAt,
"updated_at": v.UpdatedAt,
}
@@ -60,6 +64,7 @@ func flattenLogicalPort(d *schema.ResourceData, logicalPort *logicalports.Logica
d.Set("description", logicalPort.Description)
d.Set("display_name", logicalPort.DisplayName)
d.Set("enabled", logicalPort.Enabled)
d.Set("external_network_id", logicalPort.ExternalNetworkID)
d.Set("hypervisor", logicalPort.Hypervisor)
d.Set("hypervisor_display_name", logicalPort.HypervisorDisplayName)
d.Set("live_migration_target_hv", logicalPort.LiveMigrationTargetHV)
@@ -67,32 +72,63 @@ func flattenLogicalPort(d *schema.ResourceData, logicalPort *logicalports.Logica
d.Set("unique_identifier", logicalPort.UniqueIdentifier)
d.Set("version_id", logicalPort.VersionID)
d.Set("bindings", flattenBindings(logicalPort.Bindings))
d.Set("labels", flattenLabels(logicalPort.Labels))
d.Set("created_at", logicalPort.CreatedAt)
d.Set("updated_at", logicalPort.UpdatedAt)
}
func flattenLabels(labels logicalports.Labels) []map[string]interface{} {
if labels.VMID == "" && labels.VMName == "" {
return []map[string]interface{}{}
}
return []map[string]interface{}{
{
"vm_id": labels.VMID,
"vm_name": labels.VMName,
},
}
}
func flattenBindings(bindings logicalports.Bindings) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"id": bindings.ID,
"segment_id": bindings.SegmentID,
"segment_display_name": bindings.SegmentDisplayName,
"port_security": bindings.PortSecurity,
"address_detection": bindings.AddressDetection,
"is_excluded_from_firewall": bindings.IsExcludedFromFirewall,
"version_id": bindings.VersionID,
"created_at": bindings.CreatedAt,
"updated_at": bindings.UpdatedAt,
"id": bindings.ID,
"segment_id": bindings.SegmentID,
"segment_display_name": bindings.SegmentDisplayName,
"port_security": bindings.PortSecurity,
"address_detection": bindings.AddressDetection,
"version_id": bindings.VersionID,
"created_at": bindings.CreatedAt,
"updated_at": bindings.UpdatedAt,
"logical_port_addresses": flattenLogicalPortAddresses(bindings.LogicalPortAddresses),
}
res = append(res, temp)
return res
}
func flattenLogicalPortAddresses(addrs []logicalports.LogicalPortAddress) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(addrs))
for _, a := range addrs {
res = append(res, map[string]interface{}{
"ip": a.IP,
"ip_type": a.IPType,
"mac": a.MAC,
"id": a.ID,
"logical_port_id": a.LogicalPortID,
"assigned_at": a.AssignedAt,
"is_discovered": a.IsDiscovered,
"is_primary": a.IsPrimary,
})
}
return res
}
func flattenStatus(status logicalports.Status) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"common": status.Common,
"hypervisors": flattenHypervisors(status.Hypervisors),
"operation_status": status.OperationStatus,
"hypervisor_status": status.HypervisorStatus,
"hypervisors": flattenHypervisors(status.Hypervisors),
}
res = append(res, temp)
return res
@@ -102,7 +138,7 @@ func flattenHypervisors(hv []logicalports.HypervisorStatus) []map[string]interfa
res := make([]map[string]interface{}, 0, len(hv))
for _, v := range hv {
temp := map[string]interface{}{
"status": v.Status,
"operation_status": v.OperationStatus,
"name": v.Name,
"display_name": v.DisplayName,
"hypervisor_status": v.HypervisorStatus,

View File

@@ -17,14 +17,13 @@ func resourceLogicalPortCreate(ctx context.Context, d *schema.ResourceData, m in
c := m.(*controller.ControllerCfg)
req := logicalports.CreateRequest{
AccessGroupID: d.Get("access_group_id").(string),
Description: d.Get("description").(string),
DisplayName: d.Get("display_name").(string),
Enabled: d.Get("enabled").(bool),
IsExcludedFromFirewall: d.Get("is_excluded_from_firewall").(bool),
Hypervisor: d.Get("hypervisor").(string),
PortSecurity: d.Get("port_security").(bool),
SegmentID: d.Get("segment_id").(string),
AccessGroupID: d.Get("access_group_id").(string),
Description: d.Get("description").(string),
DisplayName: d.Get("display_name").(string),
Enabled: d.Get("enabled").(bool),
Hypervisor: d.Get("hypervisor").(string),
PortSecurity: d.Get("port_security").(bool),
SegmentID: d.Get("segment_id").(string),
}
if adapterMAC, ok := d.GetOk("adapter_mac"); ok {
@@ -33,6 +32,16 @@ func resourceLogicalPortCreate(ctx context.Context, d *schema.ResourceData, m in
if uniqueID, ok := d.GetOk("unique_identifier"); ok {
req.UniqueIdentifier = uniqueID.(string)
}
if labelsRaw, ok := d.GetOk("labels"); ok {
labelsList := labelsRaw.([]interface{})
if len(labelsList) > 0 {
labelsMap := labelsList[0].(map[string]interface{})
req.Labels = logicalports.CreateLabels{
VMID: labelsMap["vm_id"].(string),
VMName: labelsMap["vm_name"].(string),
}
}
}
if logicalPortAddresses, ok := d.GetOk("logical_port_addresses"); ok {
logicalPortAddressesList := logicalPortAddresses.([]interface{})
logicalPortsAddressesArr := make([]logicalports.LogicalPortAddress, 0)
@@ -46,7 +55,7 @@ func resourceLogicalPortCreate(ctx context.Context, d *schema.ResourceData, m in
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
}
if mac, ok := logicalPortAddressMap["mac_address"]; ok {
if mac, ok := logicalPortAddressMap["mac"]; ok {
logicalPortAddress.MAC = mac.(string)
}
logicalPortsAddressesArr = append(logicalPortsAddressesArr, logicalPortAddress)
@@ -84,17 +93,37 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
log.Debugf("resourceLogicalPortUpdate: called logical port with id %s", d.Id())
c := m.(*controller.ControllerCfg)
migrate := d.Get("migrate").(bool)
req := logicalports.UpdateRequest{
LogicalPortID: d.Id(),
VersionID: uint64(d.Get("version_id").(int)),
AdapterMAC: d.Get("adapter_mac").(string),
Description: d.Get("description").(string),
DisplayName: d.Get("display_name").(string),
Enabled: d.Get("enabled").(bool),
Hypervisor: d.Get("hypervisor").(string),
PortSecurity: d.Get("port_security").(bool),
IsExcludedFromFirewall: d.Get("is_excluded_from_firewall").(bool),
SegmentID: d.Get("segment_id").(string),
LogicalPortID: d.Id(),
VersionID: uint64(d.Get("version_id").(int)),
AdapterMAC: d.Get("adapter_mac").(string),
Description: d.Get("description").(string),
DisplayName: d.Get("display_name").(string),
Enabled: d.Get("enabled").(bool),
PortSecurity: d.Get("port_security").(bool),
SegmentID: d.Get("segment_id").(string),
}
if !migrate {
req.Hypervisor = d.Get("hypervisor").(string)
} else {
old, _ := d.GetChange("hypervisor")
req.Hypervisor = old.(string)
}
if d.HasChange("labels") {
if labelsRaw, ok := d.GetOk("labels"); ok {
labelsList := labelsRaw.([]interface{})
if len(labelsList) > 0 {
labelsMap := labelsList[0].(map[string]interface{})
req.Labels = logicalports.UpdateLabels{
VMID: labelsMap["vm_id"].(string),
VMName: labelsMap["vm_name"].(string),
}
}
}
}
if d.HasChange("logical_port_addresses") {
@@ -112,7 +141,7 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
}
if mac, ok := logicalPortAddressMap["mac_address"]; ok {
if mac, ok := logicalPortAddressMap["mac"]; ok {
logicalPortAddress.MAC = mac.(string)
}
oldAddressesMap[logicalPortAddress.IP] = logicalPortAddress
@@ -128,19 +157,19 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
}
if mac, ok := logicalPortAddressMap["mac_address"]; ok {
if mac, ok := logicalPortAddressMap["mac"]; ok {
logicalPortAddress.MAC = mac.(string)
}
newAddressesMap[logicalPortAddress.IP] = logicalPortAddress
}
for addressIP, _ := range oldAddressesMap {
removeAddresses := make([]string, 0)
removeAddresses := make([]string, 0)
for addressIP := range oldAddressesMap {
if _, exists := newAddressesMap[addressIP]; !exists {
removeAddresses = append(removeAddresses, addressIP)
}
req.RemoveAddresses = removeAddresses
}
req.RemoveAddresses = removeAddresses
for addressIP, address := range newAddressesMap {
if oldAddressIP, exists := oldAddressesMap[addressIP]; !exists || address != oldAddressIP {
@@ -174,6 +203,34 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
return diag.FromErr(err)
}
if migrate {
if targetHV, ok := d.GetOk("hypervisor"); ok {
// Re-read version_id
lp, err := utilityLogicalPortCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
migrateReq := logicalports.MigrateStartRequest{
LogicalPortID: d.Id(),
VersionID: lp.VersionID,
TargetHypervisor: targetHV.(string),
}
_, err = c.SDN().LogicalPorts().StartMigrate(ctx, migrateReq)
if err != nil {
return diag.FromErr(err)
}
// to prevent drift on the next plan
diags := resourceLogicalPortRead(ctx, d, m)
if diags.HasError() {
return diags
}
d.Set("hypervisor", targetHV.(string))
return diags
}
}
return resourceLogicalPortRead(ctx, d, m)
}

View File

@@ -5,6 +5,49 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func logicalPortAddressesSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Computed: true,
},
"ip_type": {
Type: schema.TypeString,
Computed: true,
},
"mac": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeString,
Computed: true,
},
"logical_port_id": {
Type: schema.TypeString,
Computed: true,
},
"assigned_at": {
Type: schema.TypeString,
Computed: true,
},
"is_discovered": {
Type: schema.TypeBool,
Computed: true,
},
"is_primary": {
Type: schema.TypeBool,
Computed: true,
},
},
},
}
}
func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"access_group_id": {
@@ -27,10 +70,6 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Required: true,
Description: "Whether the logical port should be enabled",
},
"is_excluded_from_firewall": {
Type: schema.TypeBool,
Required: true,
},
"hypervisor": {
Type: schema.TypeString,
Required: true,
@@ -61,6 +100,12 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Optional: true,
Default: false,
},
"migrate": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint.",
},
"logical_port_addresses": {
Type: schema.TypeList,
Optional: true,
@@ -127,20 +172,25 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"common": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Common status",
Description: "Operation status",
},
"hypervisor_status": {
Type: schema.TypeString,
Computed: true,
Description: "Hypervisor status",
},
"hypervisors": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"status": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Status of the hypervisor",
Description: "Operation status of the hypervisor",
},
"name": {
Type: schema.TypeString,
@@ -198,10 +248,6 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "If the adapter address detection is enabled",
},
"is_excluded_from_firewall": {
Type: schema.TypeBool,
Computed: true,
},
"version_id": {
Type: schema.TypeInt,
Computed: true,
@@ -217,6 +263,7 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time of the binding",
},
"logical_port_addresses": logicalPortAddressesSchema(),
},
},
},
@@ -225,6 +272,29 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Version ID of the logical port",
},
"labels": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"vm_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "VM ID label",
},
"vm_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "VM name label",
},
},
},
Description: "Labels",
},
}
return res
}
@@ -322,6 +392,21 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"asc", "dec"}, false),
},
"operation_status": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
"Idle", "SynchronizingAtCore", "SynchronizingAtOVN",
"Synchronized", "NoHypervisorAtOVN", "FailedAtCore", "TemporaryFailedAtCore",
}, false),
Description: "Filter by operation status",
},
"hypervisor_status": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"Up", "Warning", "Error"}, false),
Description: "Filter by hypervisor status",
},
"items": {
Type: schema.TypeList,
Computed: true,
@@ -377,6 +462,10 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Display name of the hypervisor",
},
"external_network_id": {
Type: schema.TypeString,
Computed: true,
},
"live_migration_target_hv": {
Type: schema.TypeString,
Computed: true,
@@ -386,20 +475,25 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"common": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Common status",
Description: "Operation status",
},
"hypervisor_status": {
Type: schema.TypeString,
Computed: true,
Description: "Hypervisor status",
},
"hypervisors": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"status": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Status of the hypervisor",
Description: "Operation status of the hypervisor",
},
"name": {
Type: schema.TypeString,
@@ -467,10 +561,6 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "If the adapter address detection is enabled",
},
"is_excluded_from_firewall": {
Type: schema.TypeBool,
Computed: true,
},
"version_id": {
Type: schema.TypeInt,
Computed: true,
@@ -486,6 +576,7 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time of the binding",
},
"logical_port_addresses": logicalPortAddressesSchema(),
},
},
},
@@ -499,6 +590,25 @@ func dataSourceLogicalPortListSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time the logical port",
},
"labels": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"vm_id": {
Type: schema.TypeString,
Computed: true,
Description: "VM ID label",
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
Description: "VM name label",
},
},
},
Description: "Labels",
},
},
},
},
@@ -558,6 +668,10 @@ func dataSourceLogicalPortByUniqueIDSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Display name of the hypervisor",
},
"external_network_id": {
Type: schema.TypeString,
Computed: true,
},
"live_migration_target_hv": {
Type: schema.TypeString,
Computed: true,
@@ -567,20 +681,25 @@ func dataSourceLogicalPortByUniqueIDSchemaMake() map[string]*schema.Schema {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"common": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Common status",
Description: "Operation status",
},
"hypervisor_status": {
Type: schema.TypeString,
Computed: true,
Description: "Hypervisor status",
},
"hypervisors": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"status": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Status of the hypervisor",
Description: "Operation status of the hypervisor",
},
"name": {
Type: schema.TypeString,
@@ -643,10 +762,6 @@ func dataSourceLogicalPortByUniqueIDSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "If the adapter address detection is enabled",
},
"is_excluded_from_firewall": {
Type: schema.TypeBool,
Computed: true,
},
"version_id": {
Type: schema.TypeInt,
Computed: true,
@@ -662,6 +777,7 @@ func dataSourceLogicalPortByUniqueIDSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time of the binding",
},
"logical_port_addresses": logicalPortAddressesSchema(),
},
},
},
@@ -675,6 +791,25 @@ func dataSourceLogicalPortByUniqueIDSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time the logical port",
},
"labels": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"vm_id": {
Type: schema.TypeString,
Computed: true,
Description: "VM ID label",
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
Description: "VM name label",
},
},
},
Description: "Labels",
},
}
return res
}
@@ -731,6 +866,10 @@ func dataSourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Display name of the hypervisor",
},
"external_network_id": {
Type: schema.TypeString,
Computed: true,
},
"live_migration_target_hv": {
Type: schema.TypeString,
Computed: true,
@@ -740,20 +879,25 @@ func dataSourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"common": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Common status",
Description: "Operation status",
},
"hypervisor_status": {
Type: schema.TypeString,
Computed: true,
Description: "Hypervisor status",
},
"hypervisors": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"status": {
"operation_status": {
Type: schema.TypeString,
Computed: true,
Description: "Status of the hypervisor",
Description: "Operation status of the hypervisor",
},
"name": {
Type: schema.TypeString,
@@ -821,10 +965,6 @@ func dataSourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "If the adapter address detection is enabled",
},
"is_excluded_from_firewall": {
Type: schema.TypeBool,
Computed: true,
},
"version_id": {
Type: schema.TypeInt,
Computed: true,
@@ -840,6 +980,7 @@ func dataSourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time of the binding",
},
"logical_port_addresses": logicalPortAddressesSchema(),
},
},
},
@@ -853,6 +994,25 @@ func dataSourceLogicalPortSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Update time the logical port",
},
"labels": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"vm_id": {
Type: schema.TypeString,
Computed: true,
Description: "VM ID label",
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
Description: "VM name label",
},
},
},
Description: "Labels",
},
}
return res
}

View File

@@ -69,6 +69,12 @@ func utilityLogicalPortListCheckPresence(ctx context.Context, d *schema.Resource
if sortOrder, ok := d.GetOk("sort_order"); ok {
req.SortOrder = sortOrder.(string)
}
if operationStatus, ok := d.GetOk("operation_status"); ok {
req.OperationStatus = operationStatus.(string)
}
if hypervisorStatus, ok := d.GetOk("hypervisor_status"); ok {
req.HypervisorStatus = hypervisorStatus.(string)
}
logicalPortList, err := c.SDN().LogicalPorts().List(ctx, req)
if err != nil {