@@ -124,7 +124,49 @@ func (s *Service) GetPortForExternalNetwork(instanceID string, externalNetworkID
124124 return nil , nil
125125}
126126
127- func (s * Service ) CreatePort (eventObject runtime.Object , portSpec * infrav1.ResolvedPortSpec ) (* ports.Port , error ) {
127+ // ensurePortTagsAndTrunk ensures that the provided port has the tags and trunk defined in portSpec.
128+ func (s * Service ) ensurePortTagsAndTrunk (port * ports.Port , eventObject runtime.Object , portSpec * infrav1.ResolvedPortSpec ) error {
129+ if len (portSpec .Tags ) > 0 {
130+ if err := s .replaceAllAttributesTags (eventObject , portResource , port .ID , portSpec .Tags ); err != nil {
131+ record .Warnf (eventObject , "FailedReplaceTags" , "Failed to replace port tags %s: %v" , portSpec .Name , err )
132+ return err
133+ }
134+ }
135+ if ptr .Deref (portSpec .Trunk , false ) {
136+ trunk , err := s .getOrCreateTrunkForPort (eventObject , port )
137+ if err != nil {
138+ record .Warnf (eventObject , "FailedCreateTrunk" , "Failed to create trunk for port %s: %v" , port .Name , err )
139+ return err
140+ }
141+ if err = s .replaceAllAttributesTags (eventObject , trunkResource , trunk .ID , portSpec .Tags ); err != nil {
142+ record .Warnf (eventObject , "FailedReplaceTags" , "Failed to replace trunk tags %s: %v" , port .Name , err )
143+ return err
144+ }
145+ }
146+ return nil
147+ }
148+
149+ // EnsurePort ensure that a port defined with portSpec Name and NetworkID exists,
150+ // and that the port has suitable tags and trunk.
151+ func (s * Service ) EnsurePort (eventObject runtime.Object , portSpec * infrav1.ResolvedPortSpec ) (* ports.Port , error ) {
152+ existingPorts , err := s .client .ListPort (ports.ListOpts {
153+ Name : portSpec .Name ,
154+ NetworkID : portSpec .NetworkID ,
155+ })
156+ if err != nil {
157+ return nil , fmt .Errorf ("searching for existing port for server: %v" , err )
158+ }
159+ if len (existingPorts ) > 1 {
160+ return nil , fmt .Errorf ("multiple ports found with name \" %s\" " , portSpec .Name )
161+ }
162+
163+ if len (existingPorts ) == 1 {
164+ port := & existingPorts [0 ]
165+ if err = s .ensurePortTagsAndTrunk (port , eventObject , portSpec ); err != nil {
166+ return nil , err
167+ }
168+ return port , nil
169+ }
128170 var addressPairs []ports.AddressPair
129171 if ! ptr .Deref (portSpec .DisablePortSecurity , false ) {
130172 for _ , ap := range portSpec .AllowedAddressPairs {
@@ -200,24 +242,10 @@ func (s *Service) CreatePort(eventObject runtime.Object, portSpec *infrav1.Resol
200242 return nil , err
201243 }
202244
203- if len (portSpec .Tags ) > 0 {
204- if err = s .replaceAllAttributesTags (eventObject , portResource , port .ID , portSpec .Tags ); err != nil {
205- record .Warnf (eventObject , "FailedReplaceTags" , "Failed to replace port tags %s: %v" , portSpec .Name , err )
206- return nil , err
207- }
245+ if err = s .ensurePortTagsAndTrunk (port , eventObject , portSpec ); err != nil {
246+ return nil , err
208247 }
209248 record .Eventf (eventObject , "SuccessfulCreatePort" , "Created port %s with id %s" , port .Name , port .ID )
210- if ptr .Deref (portSpec .Trunk , false ) {
211- trunk , err := s .getOrCreateTrunkForPort (eventObject , port )
212- if err != nil {
213- record .Warnf (eventObject , "FailedCreateTrunk" , "Failed to create trunk for port %s: %v" , port .Name , err )
214- return nil , err
215- }
216- if err = s .replaceAllAttributesTags (eventObject , trunkResource , trunk .ID , portSpec .Tags ); err != nil {
217- record .Warnf (eventObject , "FailedReplaceTags" , "Failed to replace trunk tags %s: %v" , port .Name , err )
218- return nil , err
219- }
220- }
221249
222250 return port , nil
223251}
@@ -328,16 +356,12 @@ func getPortName(baseName string, portSpec *infrav1.PortOpts, netIndex int) stri
328356 return fmt .Sprintf ("%s-%d" , baseName , netIndex )
329357}
330358
331- func (s * Service ) CreatePorts (eventObject runtime.Object , desiredPorts []infrav1.ResolvedPortSpec , resources * infrav1alpha1.ServerResources ) error {
332- for i := range desiredPorts {
333- // Skip creation of ports which already exist
334- if i < len (resources .Ports ) {
335- continue
336- }
337-
338- portSpec := & desiredPorts [i ]
339- // Events are recorded in CreatePort
340- port , err := s .CreatePort (eventObject , portSpec )
359+ // EnsurePorts ensures that every one of desiredPorts is created and has
360+ // expected trunk and tags.
361+ func (s * Service ) EnsurePorts (eventObject runtime.Object , desiredPorts []infrav1.ResolvedPortSpec , resources * infrav1alpha1.ServerResources ) error {
362+ for _ , portSpec := range desiredPorts {
363+ // Events are recorded in EnsurePort
364+ port , err := s .EnsurePort (eventObject , & portSpec )
341365 if err != nil {
342366 return err
343367 }
0 commit comments