@@ -30,6 +30,9 @@ import (
30
30
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
31
31
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
32
32
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
33
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
34
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
35
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
33
36
"github.com/gophercloud/gophercloud/pagination"
34
37
"github.com/mitchellh/mapstructure"
35
38
v1 "k8s.io/api/core/v1"
@@ -48,6 +51,7 @@ import (
48
51
// Instances encapsulates an implementation of Instances for OpenStack.
49
52
type Instances struct {
50
53
compute * gophercloud.ServiceClient
54
+ network * gophercloud.ServiceClient
51
55
region string
52
56
regionProviderID bool
53
57
opts metadata.Opts
@@ -148,13 +152,20 @@ func (os *OpenStack) instances() (*Instances, bool) {
148
152
return nil , false
149
153
}
150
154
155
+ network , err := client .NewNetworkV2 (os .provider , os .epOpts )
156
+ if err != nil {
157
+ klog .Errorf ("Failed to create an OpenStack Network client: %v" , err )
158
+ return nil , false
159
+ }
160
+
151
161
regionalProviderID := false
152
162
if isRegionalProviderID := sysos .Getenv (RegionalProviderIDEnv ); isRegionalProviderID == "true" {
153
163
regionalProviderID = true
154
164
}
155
165
156
166
return & Instances {
157
167
compute : compute ,
168
+ network : network ,
158
169
region : os .epOpts .Region ,
159
170
regionProviderID : regionalProviderID ,
160
171
opts : os .metadataOpts ,
@@ -193,7 +204,7 @@ func (i *Instances) AddSSHKeyToAllInstances(ctx context.Context, user string, ke
193
204
func (i * Instances ) NodeAddresses (ctx context.Context , name types.NodeName ) ([]v1.NodeAddress , error ) {
194
205
klog .V (4 ).Infof ("NodeAddresses(%v) called" , name )
195
206
196
- addrs , err := getAddressesByName (i .compute , name , i .networkingOpts )
207
+ addrs , err := getAddressesByName (i .compute , name , i .networkingOpts , i . network )
197
208
if err != nil {
198
209
return nil , err
199
210
}
@@ -226,7 +237,7 @@ func (i *Instances) NodeAddressesByProviderID(ctx context.Context, providerID st
226
237
return []v1.NodeAddress {}, err
227
238
}
228
239
229
- interfaces , err := getAttachedInterfacesByID (i .compute , server .ID )
240
+ interfaces , err := getAttachedInterfacesByID (i .compute , server .ID , i . network )
230
241
if err != nil {
231
242
return []v1.NodeAddress {}, err
232
243
}
@@ -332,7 +343,7 @@ func (i *Instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
332
343
return nil , err
333
344
}
334
345
335
- interfaces , err := getAttachedInterfacesByID (i .compute , srv .ID )
346
+ interfaces , err := getAttachedInterfacesByID (i .compute , srv .ID , i . network )
336
347
if err != nil {
337
348
return nil , err
338
349
}
@@ -565,9 +576,15 @@ func getServerByName(client *gophercloud.ServiceClient, name types.NodeName) (*S
565
576
// * metadata hostname
566
577
// * server object Addresses (floating type)
567
578
func nodeAddresses (srv * servers.Server , interfaces []attachinterfaces.Interface , networkingOpts NetworkingOpts ) ([]v1.NodeAddress , error ) {
579
+ type Address struct {
580
+ IPType string `mapstructure:"OS-EXT-IPS:type"`
581
+ Addr string
582
+ }
583
+
568
584
addrs := []v1.NodeAddress {}
569
585
570
586
// parse private IP addresses first in an ordered manner
587
+ allPrivates := make (map [string ][]Address )
571
588
for _ , iface := range interfaces {
572
589
for _ , fixedIP := range iface .FixedIPs {
573
590
if iface .PortState == "ACTIVE" {
@@ -579,6 +596,10 @@ func nodeAddresses(srv *servers.Server, interfaces []attachinterfaces.Interface,
579
596
Address : fixedIP .IPAddress ,
580
597
},
581
598
)
599
+ if len (iface .NetID ) > 0 {
600
+ addr := Address {IPType : "fixed" , Addr : fixedIP .IPAddress }
601
+ allPrivates [iface .NetID ] = append (allPrivates [iface .NetID ], addr )
602
+ }
582
603
}
583
604
}
584
605
}
@@ -613,17 +634,40 @@ func nodeAddresses(srv *servers.Server, interfaces []attachinterfaces.Interface,
613
634
}
614
635
615
636
// process the rest
616
- type Address struct {
617
- IPType string `mapstructure:"OS-EXT-IPS:type"`
618
- Addr string
619
- }
620
-
621
637
var addresses map [string ][]Address
622
638
err := mapstructure .Decode (srv .Addresses , & addresses )
623
639
if err != nil {
624
640
return nil , err
625
641
}
626
642
643
+ // add subports if exist to the server
644
+ extraPrivates := make (map [string ][]Address )
645
+ for k , v := range allPrivates {
646
+ ok := false
647
+ for _ , a := range v {
648
+ for _ , v1 := range addresses {
649
+ for _ , a1 := range v1 {
650
+ if a .Addr == a1 .Addr {
651
+ ok = true
652
+ break
653
+ }
654
+ }
655
+ }
656
+ }
657
+ if ! ok {
658
+ extraPrivates [k ] = v
659
+ }
660
+ }
661
+ klog .V (5 ).Infof ("Node '%s' extraPrivates '%s'" , srv .Name , extraPrivates )
662
+ for k , v := range extraPrivates {
663
+ v1 , ok := addresses [k ]
664
+ if ! ok {
665
+ addresses [k ] = v
666
+ } else {
667
+ addresses [k ] = append (v1 , v ... )
668
+ }
669
+ }
670
+
627
671
var networks []string
628
672
for k := range addresses {
629
673
networks = append (networks , k )
@@ -677,26 +721,91 @@ func nodeAddresses(srv *servers.Server, interfaces []attachinterfaces.Interface,
677
721
return addrs , nil
678
722
}
679
723
680
- func getAddressesByName (client * gophercloud.ServiceClient , name types.NodeName , networkingOpts NetworkingOpts ) ([]v1.NodeAddress , error ) {
681
- srv , err := getServerByName (client , name )
724
+ func getAddressesByName (compute * gophercloud.ServiceClient , name types.NodeName , networkingOpts NetworkingOpts , network * gophercloud. ServiceClient ) ([]v1.NodeAddress , error ) {
725
+ srv , err := getServerByName (compute , name )
682
726
if err != nil {
683
727
return nil , err
684
728
}
685
729
686
- interfaces , err := getAttachedInterfacesByID (client , srv .ID )
730
+ interfaces , err := getAttachedInterfacesByID (compute , srv .ID , network )
687
731
if err != nil {
688
732
return nil , err
689
733
}
690
734
691
735
return nodeAddresses (& srv .Server , interfaces , networkingOpts )
692
736
}
693
737
738
+ // getSubInterfaces
739
+ func getSubInterfaces (network * gophercloud.ServiceClient ) ([]attachinterfaces.Interface , error ) {
740
+ var interfaces []attachinterfaces.Interface
741
+
742
+ // Check if trunk ports are attached
743
+ listOpts := trunks.ListOpts {}
744
+ allPages , err := trunks .List (network , listOpts ).AllPages ()
745
+ if err != nil {
746
+ klog .Errorf ("Failed to list trunks: %v" , err )
747
+ return interfaces , err
748
+ }
749
+ allTrunks , err := trunks .ExtractTrunks (allPages )
750
+ if err != nil {
751
+ klog .Errorf ("Failed to extract trunks: %v" , err )
752
+ return interfaces , err
753
+ }
754
+
755
+ // Get subports attached to the trunk
756
+ var subports []trunks.Subport
757
+ for _ , trunk := range allTrunks {
758
+ for _ , iface := range interfaces {
759
+ if iface .PortID == trunk .PortID {
760
+ s , err := trunks .GetSubports (network , trunk .ID ).Extract ()
761
+ if err != nil {
762
+ klog .Errorf ("Failed to get subports for trunk %s: %v" , trunk .ID , err )
763
+ return interfaces , err
764
+ }
765
+ subports = append (subports , s ... )
766
+ }
767
+ }
768
+ }
769
+ klog .V (5 ).Infof ("subports %v" , subports )
770
+
771
+ // Arrange subports as for directly attached ports
772
+ for _ , sport := range subports {
773
+ p , err := ports .Get (network , sport .PortID ).Extract ()
774
+ if err != nil {
775
+ klog .Errorf ("Failed to get port info for subport %s: %v" , sport .PortID , err )
776
+ return interfaces , err
777
+ }
778
+ n , err := networks .Get (network , p .NetworkID ).Extract ()
779
+ if err != nil {
780
+ klog .Errorf ("Failed to get network info for subport %s: %v" , sport .PortID , err )
781
+ return interfaces , err
782
+ }
783
+ var iface = attachinterfaces.Interface {
784
+ PortState : "ACTIVE" ,
785
+ FixedIPs : []attachinterfaces.FixedIP {},
786
+ PortID : p .ID ,
787
+ NetID : n .Name ,
788
+ MACAddr : p .MACAddress ,
789
+ }
790
+ for _ , ip := range p .FixedIPs {
791
+ var ip2 = attachinterfaces.FixedIP {
792
+ SubnetID : ip .SubnetID ,
793
+ IPAddress : ip .IPAddress ,
794
+ }
795
+ iface .FixedIPs = append (iface .FixedIPs , ip2 )
796
+ }
797
+ interfaces = append (interfaces , iface )
798
+ }
799
+ klog .V (5 ).Infof ("interfaces %v" , interfaces )
800
+ return interfaces , nil
801
+ }
802
+
694
803
// getAttachedInterfacesByID returns the node interfaces of the specified instance.
695
- func getAttachedInterfacesByID (client * gophercloud.ServiceClient , serviceID string ) ([]attachinterfaces.Interface , error ) {
804
+ func getAttachedInterfacesByID (compute * gophercloud.ServiceClient , serviceID string , network * gophercloud. ServiceClient ) ([]attachinterfaces.Interface , error ) {
696
805
var interfaces []attachinterfaces.Interface
697
806
698
807
mc := metrics .NewMetricContext ("server_os_interface" , "list" )
699
- pager := attachinterfaces .List (client , serviceID )
808
+ pager := attachinterfaces .List (compute , serviceID )
700
809
err := pager .EachPage (func (page pagination.Page ) (bool , error ) {
701
810
s , err := attachinterfaces .ExtractInterfaces (page )
702
811
if err != nil {
@@ -708,6 +817,10 @@ func getAttachedInterfacesByID(client *gophercloud.ServiceClient, serviceID stri
708
817
if mc .ObserveRequest (err ) != nil {
709
818
return interfaces , err
710
819
}
711
-
820
+ subInterfaces , err := getSubInterfaces (network )
821
+ if err != nil {
822
+ return interfaces , err
823
+ }
824
+ interfaces = append (interfaces , subInterfaces ... )
712
825
return interfaces , nil
713
826
}
0 commit comments