diff --git a/cmd/kops/create_cluster.go b/cmd/kops/create_cluster.go index 3c67a37df3..614cdc5673 100644 --- a/cmd/kops/create_cluster.go +++ b/cmd/kops/create_cluster.go @@ -151,6 +151,7 @@ type CreateClusterOptions struct { // OpenstackExternalNet is the name of the external network for the openstack router OpenstackExternalNet string + OpenstackExternalSubnet string OpenstackStorageIgnoreAZ bool OpenstackDNSServers string OpenstackLbSubnet string @@ -384,6 +385,7 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command { if cloudup.AlphaAllowOpenstack.Enabled() { // Openstack flags cmd.Flags().StringVar(&options.OpenstackExternalNet, "os-ext-net", options.OpenstackExternalNet, "The name of the external network to use with the openstack router") + cmd.Flags().StringVar(&options.OpenstackExternalSubnet, "os-ext-subnet", options.OpenstackExternalSubnet, "The name of the external floating subnet to use with the openstack router") cmd.Flags().StringVar(&options.OpenstackLbSubnet, "os-lb-floating-subnet", options.OpenstackLbSubnet, "The name of the external subnet to use with the kubernetes api") cmd.Flags().BoolVar(&options.OpenstackStorageIgnoreAZ, "os-kubelet-ignore-az", options.OpenstackStorageIgnoreAZ, "If true kubernetes may attach volumes across availability zones") cmd.Flags().BoolVar(&options.OpenstackLBOctavia, "os-octavia", options.OpenstackLBOctavia, "If true octavia loadbalancer api will be used") @@ -937,6 +939,9 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e if c.OpenstackDNSServers != "" { cluster.Spec.CloudConfig.Openstack.Router.DNSServers = fi.String(c.OpenstackDNSServers) } + if c.OpenstackExternalSubnet != "" { + cluster.Spec.CloudConfig.Openstack.Router.ExternalSubnet = fi.String(c.OpenstackExternalSubnet) + } if c.OpenstackLbSubnet != "" { cluster.Spec.CloudConfig.Openstack.Loadbalancer.FloatingSubnet = fi.String(c.OpenstackLbSubnet) } diff --git a/pkg/apis/kops/componentconfig.go b/pkg/apis/kops/componentconfig.go index 426b7dcd79..ae5cc45e50 100644 --- a/pkg/apis/kops/componentconfig.go +++ b/pkg/apis/kops/componentconfig.go @@ -530,6 +530,7 @@ type OpenstackMonitor struct { type OpenstackRouter struct { ExternalNetwork *string `json:"externalNetwork,omitempty"` DNSServers *string `json:"dnsServers,omitempty"` + ExternalSubnet *string `json:"externalSubnet,omitempty"` } // OpenstackConfiguration defines cloud config elements for the openstack cloud provider diff --git a/pkg/apis/kops/v1alpha1/componentconfig.go b/pkg/apis/kops/v1alpha1/componentconfig.go index 109ddce817..deebfa3dbf 100644 --- a/pkg/apis/kops/v1alpha1/componentconfig.go +++ b/pkg/apis/kops/v1alpha1/componentconfig.go @@ -530,6 +530,7 @@ type OpenstackMonitor struct { type OpenstackRouter struct { ExternalNetwork *string `json:"externalNetwork,omitempty"` DNSServers *string `json:"dnsServers,omitempty"` + ExternalSubnet *string `json:"externalSubnet,omitempty"` } // OpenstackConfiguration defines cloud config elements for the openstack cloud provider diff --git a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go index 165e3f38cd..351fec8d08 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.conversion.go @@ -4103,6 +4103,7 @@ func Convert_kops_OpenstackMonitor_To_v1alpha1_OpenstackMonitor(in *kops.Opensta func autoConvert_v1alpha1_OpenstackRouter_To_kops_OpenstackRouter(in *OpenstackRouter, out *kops.OpenstackRouter, s conversion.Scope) error { out.ExternalNetwork = in.ExternalNetwork out.DNSServers = in.DNSServers + out.ExternalSubnet = in.ExternalSubnet return nil } @@ -4114,6 +4115,7 @@ func Convert_v1alpha1_OpenstackRouter_To_kops_OpenstackRouter(in *OpenstackRoute func autoConvert_kops_OpenstackRouter_To_v1alpha1_OpenstackRouter(in *kops.OpenstackRouter, out *OpenstackRouter, s conversion.Scope) error { out.ExternalNetwork = in.ExternalNetwork out.DNSServers = in.DNSServers + out.ExternalSubnet = in.ExternalSubnet return nil } diff --git a/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go index 4cde1fc934..37657463a2 100644 --- a/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/kops/v1alpha1/zz_generated.deepcopy.go @@ -2716,6 +2716,11 @@ func (in *OpenstackRouter) DeepCopyInto(out *OpenstackRouter) { *out = new(string) **out = **in } + if in.ExternalSubnet != nil { + in, out := &in.ExternalSubnet, &out.ExternalSubnet + *out = new(string) + **out = **in + } return } diff --git a/pkg/apis/kops/v1alpha2/componentconfig.go b/pkg/apis/kops/v1alpha2/componentconfig.go index 13db5e2bd4..7eb5eef493 100644 --- a/pkg/apis/kops/v1alpha2/componentconfig.go +++ b/pkg/apis/kops/v1alpha2/componentconfig.go @@ -530,6 +530,7 @@ type OpenstackMonitor struct { type OpenstackRouter struct { ExternalNetwork *string `json:"externalNetwork,omitempty"` DNSServers *string `json:"dnsServers,omitempty"` + ExternalSubnet *string `json:"externalSubnet,omitempty"` } // OpenstackConfiguration defines cloud config elements for the openstack cloud provider diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index 5a5bf642aa..5a7da6fccb 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -4373,6 +4373,7 @@ func Convert_kops_OpenstackMonitor_To_v1alpha2_OpenstackMonitor(in *kops.Opensta func autoConvert_v1alpha2_OpenstackRouter_To_kops_OpenstackRouter(in *OpenstackRouter, out *kops.OpenstackRouter, s conversion.Scope) error { out.ExternalNetwork = in.ExternalNetwork out.DNSServers = in.DNSServers + out.ExternalSubnet = in.ExternalSubnet return nil } @@ -4384,6 +4385,7 @@ func Convert_v1alpha2_OpenstackRouter_To_kops_OpenstackRouter(in *OpenstackRoute func autoConvert_kops_OpenstackRouter_To_v1alpha2_OpenstackRouter(in *kops.OpenstackRouter, out *OpenstackRouter, s conversion.Scope) error { out.ExternalNetwork = in.ExternalNetwork out.DNSServers = in.DNSServers + out.ExternalSubnet = in.ExternalSubnet return nil } diff --git a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go index 16a7a06e5e..d7bbac7549 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go @@ -2787,6 +2787,11 @@ func (in *OpenstackRouter) DeepCopyInto(out *OpenstackRouter) { *out = new(string) **out = **in } + if in.ExternalSubnet != nil { + in, out := &in.ExternalSubnet, &out.ExternalSubnet + *out = new(string) + **out = **in + } return } diff --git a/pkg/apis/kops/zz_generated.deepcopy.go b/pkg/apis/kops/zz_generated.deepcopy.go index 8bab9b5704..80ba97e6f2 100644 --- a/pkg/apis/kops/zz_generated.deepcopy.go +++ b/pkg/apis/kops/zz_generated.deepcopy.go @@ -3001,6 +3001,11 @@ func (in *OpenstackRouter) DeepCopyInto(out *OpenstackRouter) { *out = new(string) **out = **in } + if in.ExternalSubnet != nil { + in, out := &in.ExternalSubnet, &out.ExternalSubnet + *out = new(string) + **out = **in + } return } diff --git a/upup/pkg/fi/cloudup/openstack/cloud.go b/upup/pkg/fi/cloudup/openstack/cloud.go index ff665c431e..0ce1f61b7a 100644 --- a/upup/pkg/fi/cloudup/openstack/cloud.go +++ b/upup/pkg/fi/cloudup/openstack/cloud.go @@ -147,6 +147,9 @@ type OpenstackCloud interface { //ListExternalNetworks will return the Neutron networks with the router:external property GetExternalNetwork() (*networks.Network, error) + // GetExternalSubnet will return the subnet for floatingip which is used in external router + GetExternalSubnet() (*subnets.Subnet, error) + // GetLBFloatingSubnet will return the subnet for floatingip which is used in lb GetLBFloatingSubnet() (*subnets.Subnet, error) @@ -273,6 +276,7 @@ type openstackCloud struct { dnsClient *gophercloud.ServiceClient lbClient *gophercloud.ServiceClient extNetworkName *string + extSubnetName *string floatingSubnet *string tags map[string]string region string @@ -376,6 +380,9 @@ func NewOpenstackCloud(tags map[string]string, spec *kops.ClusterSpec) (Openstac c.extNetworkName = spec.CloudConfig.Openstack.Router.ExternalNetwork + if spec.CloudConfig.Openstack.Router.ExternalSubnet != nil { + c.extSubnetName = spec.CloudConfig.Openstack.Router.ExternalSubnet + } if spec.CloudConfig.Openstack.Loadbalancer != nil && spec.CloudConfig.Openstack.Loadbalancer.FloatingNetworkID == nil && spec.CloudConfig.Openstack.Loadbalancer.FloatingNetwork != nil { diff --git a/upup/pkg/fi/cloudup/openstack/subnet.go b/upup/pkg/fi/cloudup/openstack/subnet.go index 32d4459ecf..5106bbfd41 100644 --- a/upup/pkg/fi/cloudup/openstack/subnet.go +++ b/upup/pkg/fi/cloudup/openstack/subnet.go @@ -87,6 +87,24 @@ func (c *openstackCloud) DeleteSubnet(subnetID string) error { } } +func (c *openstackCloud) GetExternalSubnet() (subnet *subnets.Subnet, err error) { + if c.extSubnetName == nil { + return nil, nil + } + + subnets, err := c.ListSubnets(subnets.ListOpts{ + Name: fi.StringValue(c.extSubnetName), + }) + if err != nil { + return nil, err + } + + if len(subnets) == 1 { + return &subnets[0], nil + } + return nil, fmt.Errorf("did not find floatingsubnet for external router") +} + func (c *openstackCloud) GetLBFloatingSubnet() (subnet *subnets.Subnet, err error) { if c.floatingSubnet == nil { return nil, nil diff --git a/upup/pkg/fi/cloudup/openstacktasks/router.go b/upup/pkg/fi/cloudup/openstacktasks/router.go index 8ec6233887..8079c4af7b 100644 --- a/upup/pkg/fi/cloudup/openstacktasks/router.go +++ b/upup/pkg/fi/cloudup/openstacktasks/router.go @@ -102,6 +102,18 @@ func (_ *Router) RenderOpenstack(t *openstack.OpenstackAPITarget, a, e, changes NetworkID: floatingNet.ID, } + routerFloatingSubnet, err := t.Cloud.GetExternalSubnet() + if err != nil { + return fmt.Errorf("Failed to find floatingip subnet: %v", err) + } + if routerFloatingSubnet != nil { + opt.GatewayInfo.ExternalFixedIPs = []routers.ExternalFixedIP{ + { + SubnetID: routerFloatingSubnet.ID, + }, + } + } + v, err := t.Cloud.CreateRouter(opt) if err != nil { return fmt.Errorf("Error creating router: %v", err)