Skip to content

Commit fc80c59

Browse files
Merge pull request #175 from iamemilio/portCreateRaceConditions
Bug 1948546: Port create bugs
2 parents 06c52ec + 234638e commit fc80c59

File tree

2 files changed

+42
-83
lines changed

2 files changed

+42
-83
lines changed

pkg/apis/openstackproviderconfig/v1alpha1/types.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,27 +205,30 @@ type PortOpts struct {
205205
Description string `json:"description,omitempty"`
206206
AdminStateUp *bool `json:"adminStateUp,omitempty"`
207207
MACAddress string `json:"macAddress,omitempty"`
208-
FixedIPs []ports.IP `json:"fixedIPs,omitempty"`
209-
DeviceID string `json:"deviceID,omitempty"`
210-
DeviceOwner string `json:"deviceOwner,omitempty"`
208+
FixedIPs []FixedIPs `json:"fixedIPs,omitempty"`
211209
TenantID string `json:"tenantID,omitempty"`
212210
ProjectID string `json:"projectID,omitempty"`
213211
SecurityGroups *[]string `json:"securityGroups,omitempty"`
214212
AllowedAddressPairs []ports.AddressPair `json:"allowedAddressPairs,omitempty"`
215213
Tags []string `json:"tags,omitempty"`
216214

217215
// The ID of the host where the port is allocated
218-
HostID string `json:"binding:hostID,omitempty"`
216+
HostID string `json:"hostID,omitempty"`
219217

220218
// The virtual network interface card (vNIC) type that is bound to the
221219
// neutron port.
222-
VNICType string `json:"binding:vnicType,omitempty"`
220+
VNICType string `json:"vnicType,omitempty"`
223221

224222
// enable or disable security on a given port
225223
// incompatible with securityGroups and allowedAddressPairs
226224
PortSecurity *bool `json:"portSecurity,omitempty"`
227225
}
228226

227+
type FixedIPs struct {
228+
SubnetID string `json:"subnetID"`
229+
IPAddress string `json:"ipAddress,omitempty"`
230+
}
231+
229232
type RootVolume struct {
230233
SourceType string `json:"sourceType,omitempty"`
231234
SourceUUID string `json:"sourceUUID,omitempty"`

pkg/cloud/openstack/clients/machineservice.go

Lines changed: 34 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -339,15 +339,18 @@ func getOrCreatePort(is *InstanceService, name string, portOpts openstackconfigv
339339
Description: portOpts.Description,
340340
AdminStateUp: portOpts.AdminStateUp,
341341
MACAddress: portOpts.MACAddress,
342-
DeviceID: portOpts.DeviceID,
343-
DeviceOwner: portOpts.DeviceOwner,
344342
TenantID: portOpts.TenantID,
345343
ProjectID: portOpts.ProjectID,
346344
SecurityGroups: portOpts.SecurityGroups,
347345
AllowedAddressPairs: portOpts.AllowedAddressPairs,
348346
}
349347
if len(portOpts.FixedIPs) != 0 {
350-
createOpts.FixedIPs = portOpts.FixedIPs
348+
fixedIPs := make([]ports.IP, len(portOpts.FixedIPs))
349+
for i, portOptIP := range portOpts.FixedIPs {
350+
fixedIPs[i].SubnetID = portOptIP.SubnetID
351+
fixedIPs[i].IPAddress = portOptIP.IPAddress
352+
}
353+
createOpts.FixedIPs = fixedIPs
351354
}
352355
newPort, err := ports.Create(is.networkClient, portsbinding.CreateOptsExt{
353356
CreateOptsBuilder: createOpts,
@@ -359,9 +362,14 @@ func getOrCreatePort(is *InstanceService, name string, portOpts openstackconfigv
359362
return nil, err
360363
}
361364

362-
if portOpts.PortSecurity != nil && *portOpts.PortSecurity == false {
365+
if portOpts.PortSecurity != nil {
366+
portUpdateOpts := ports.UpdateOpts{}
367+
if *portOpts.PortSecurity == false {
368+
portUpdateOpts.SecurityGroups = &[]string{}
369+
portUpdateOpts.AllowedAddressPairs = &[]ports.AddressPair{}
370+
}
363371
updateOpts := portsecurity.PortUpdateOptsExt{
364-
UpdateOptsBuilder: ports.UpdateOpts{},
372+
UpdateOptsBuilder: portUpdateOpts,
365373
PortSecurityEnabled: portOpts.PortSecurity,
366374
}
367375
err = ports.Update(is.networkClient, newPort.ID, updateOpts).ExtractInto(&portWithPortSecurityExtensions)
@@ -392,27 +400,6 @@ func listPorts(is *InstanceService, opts ports.ListOpts) ([]ports.Port, error) {
392400
return portList, nil
393401
}
394402

395-
func CreatePort(is *InstanceService, name string, net ServerNetwork, securityGroups *[]string, allowedAddressPairs *[]ports.AddressPair) (ports.Port, error) {
396-
portCreateOpts := ports.CreateOpts{
397-
Name: name,
398-
NetworkID: net.networkID,
399-
SecurityGroups: securityGroups,
400-
AllowedAddressPairs: *allowedAddressPairs,
401-
}
402-
if net.subnetID != "" {
403-
portCreateOpts.FixedIPs = []ports.IP{{SubnetID: net.subnetID}}
404-
}
405-
createOps := portsbinding.CreateOptsExt{
406-
CreateOptsBuilder: portCreateOpts,
407-
VNICType: net.vnicType,
408-
}
409-
newPort, err := ports.Create(is.networkClient, createOps).Extract()
410-
if err != nil {
411-
return ports.Port{}, fmt.Errorf("Create port for server err: %v", err)
412-
}
413-
return *newPort, nil
414-
}
415-
416403
func isDuplicate(list []string, name string) bool {
417404
if list == nil || len(list) == 0 {
418405
return false
@@ -488,7 +475,7 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
488475
return nil, err
489476
}
490477
// Get all network UUIDs
491-
var nets []ServerNetwork
478+
var nets []openstackconfigv1.PortOpts
492479
netsWithoutAllowedAddressPairs := map[string]struct{}{}
493480
for _, net := range config.Networks {
494481
opts := networks.ListOpts(net.Filter)
@@ -502,11 +489,11 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
502489
netsWithoutAllowedAddressPairs[netID] = struct{}{}
503490
}
504491
if net.Subnets == nil {
505-
nets = append(nets, ServerNetwork{
506-
networkID: netID,
507-
portTags: net.PortTags,
508-
vnicType: net.VNICType,
509-
portSecurity: net.PortSecurity,
492+
nets = append(nets, openstackconfigv1.PortOpts{
493+
NetworkID: netID,
494+
Tags: net.PortTags,
495+
VNICType: net.VNICType,
496+
PortSecurity: net.PortSecurity,
510497
})
511498
}
512499

@@ -526,12 +513,12 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
526513
return nil, err
527514
}
528515
for _, snet := range snetResults {
529-
nets = append(nets, ServerNetwork{
530-
networkID: snet.NetworkID,
531-
subnetID: snet.ID,
532-
portTags: append(net.PortTags, snetParam.PortTags...),
533-
vnicType: net.VNICType,
534-
portSecurity: portSecurity,
516+
nets = append(nets, openstackconfigv1.PortOpts{
517+
NetworkID: snet.NetworkID,
518+
FixedIPs: []openstackconfigv1.FixedIPs{{SubnetID: snet.ID}},
519+
Tags: append(net.PortTags, snetParam.PortTags...),
520+
VNICType: net.VNICType,
521+
PortSecurity: portSecurity,
535522
})
536523
}
537524
}
@@ -563,53 +550,22 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, clust
563550

564551
userData := base64.StdEncoding.EncodeToString([]byte(cmd))
565552
var portsList []servers.Network
566-
for _, net := range nets {
567-
if net.networkID == "" {
553+
for _, portOpt := range nets {
554+
if portOpt.NetworkID == "" {
568555
return nil, fmt.Errorf("No network was found or provided. Please check your machine configuration and try again")
569556
}
570-
allPages, err := ports.List(is.networkClient, ports.ListOpts{
571-
Name: name,
572-
NetworkID: net.networkID,
573-
}).AllPages()
574-
if err != nil {
575-
return nil, fmt.Errorf("Searching for existing port for server err: %v", err)
576-
}
577-
portList, err := ports.ExtractPorts(allPages)
578-
if err != nil {
579-
return nil, fmt.Errorf("Searching for existing port for server err: %v", err)
580-
}
581-
var port ports.Port
582-
if len(portList) == 0 {
583-
// create server port
584-
secGroups := &securityGroups
585-
addrPairs := &allowedAddressPairs
586-
if net.portSecurity != nil && *net.portSecurity == false {
587-
secGroups = &[]string{}
588-
addrPairs = &[]ports.AddressPair{}
589-
}
590-
if _, ok := netsWithoutAllowedAddressPairs[net.networkID]; ok {
591-
addrPairs = &[]ports.AddressPair{}
592-
}
593-
port, err = CreatePort(is, name, net, secGroups, addrPairs)
594-
if err != nil {
595-
return nil, fmt.Errorf("Failed to create port err: %v", err)
596-
}
597-
} else {
598-
port = portList[0]
557+
portOpt.SecurityGroups = &securityGroups
558+
portOpt.AllowedAddressPairs = allowedAddressPairs
559+
if _, ok := netsWithoutAllowedAddressPairs[portOpt.NetworkID]; ok {
560+
portOpt.AllowedAddressPairs = []ports.AddressPair{}
599561
}
600562

601-
// Update the port with the correct port security settings
602-
// TODO(egarcia): figure out if possible to make this part of the prior create and update api calls
603-
updateOpts := portsecurity.PortUpdateOptsExt{
604-
UpdateOptsBuilder: ports.UpdateOpts{},
605-
PortSecurityEnabled: net.portSecurity,
606-
}
607-
err = ports.Update(is.networkClient, port.ID, updateOpts).ExtractInto(&portWithPortSecurityExtensions)
563+
port, err := getOrCreatePort(is, name, portOpt)
608564
if err != nil {
609-
return nil, fmt.Errorf("Failed to update port security on port %s: %v", port.ID, err)
565+
return nil, fmt.Errorf("Failed to create port err: %v", err)
610566
}
611567

612-
portTags := deduplicateList(append(machineTags, net.portTags...))
568+
portTags := deduplicateList(append(machineTags, portOpt.Tags...))
613569
_, err = attributestags.ReplaceAll(is.networkClient, "ports", port.ID, attributestags.ReplaceAllOpts{
614570
Tags: portTags}).Extract()
615571
if err != nil {

0 commit comments

Comments
 (0)