Skip to content

Commit

Permalink
Subnet Support (#228)
Browse files Browse the repository at this point in the history
* added the ability to provide only subnet id for a network

* adding documentation for the machines.yaml for using filters, and multiple networks
  • Loading branch information
iamemilio authored and k8s-ci-robot committed Feb 20, 2019
1 parent 595d0ab commit 38d01c0
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 16 deletions.
76 changes: 75 additions & 1 deletion docs/config.md
Expand Up @@ -137,4 +137,78 @@ securityGroups:

We don't currently have specific version requriements, and so the choice is yours. However, we do require that you have either a ubuntu image or a centos image available in your cluster. For this step, we would like to refer you to the following doccumentation, https://docs.openstack.org/image-guide/obtain-images.html.

You can reference which operating system image you want to use in the machines.yaml script where it says `<Image Name>`. If you are using ubuntu, then replace `<SSH Username>` in machines.yaml with `ubuntu`. If you are using centos, then replace `<SSH Username>` in machines.yaml with `centos`.
You can reference which operating system image you want to use in the machines.yaml script where it says `<Image Name>`. If you are using ubuntu, then replace `<SSH Username>` in machines.yaml with `ubuntu`. If you are using centos, then replace `<SSH Username>` in machines.yaml with `centos`.

## Subnets
Rather than just using a network, you have the option of specifying a specific subnet to connect your server to. The following is an example of how to specify a specific subnet of a network to use for a server.

```yaml
- apiVersion: "cluster.k8s.io/v1alpha1"
kind: Machine
metadata:
generateName: openstack-node-
labels:
set: node
spec:
providerSpec:
value:
networks:
- subnet_id: < subnet id >
```

## Network Filters
If you have a complex query that you want to use to lookup a network, then you can do this by using a network filter. The filter will allow you to look up a network by the following network features:
- status
- name
- admin_state_up
- tenant_id
- project_id
- shared
- id
- marker
- limit
- sort_key
- sort_dir
- tags
- tags-any
- not-tags
- not-tags-any

By using filters to look up a network, please note that it is possible to get multiple networks as a result. This should not be a problem, however please test your filters with `openstack network list` to be certian that it returns the networks you want. Please refer to the following usage example:

```yaml
- apiVersion: "cluster.k8s.io/v1alpha1"
kind: Machine
metadata:
generateName: openstack-node-
labels:
set: node
spec:
providerSpec:
value:
networks:
- filters:
name: myNetwork
tags: myTag
```

## Multiple Networks
You can specify multiple networks (or subnets) to connect your server to. To do this, simply add another entry in the networks array. The following example connects the server to 3 different networks using all of the ways to connect discussed above:

```yaml
- apiVersion: "cluster.k8s.io/v1alpha1"
kind: Machine
metadata:
generateName: openstack-node-
labels:
set: node
spec:
providerSpec:
value:
networks:
- filters:
name: myNetwork
tags: myTag
- uuid: your_network_id
- subnet_id: your_subnet_id
```
2 changes: 2 additions & 0 deletions pkg/apis/openstackproviderconfig/v1alpha1/types.go
Expand Up @@ -78,6 +78,8 @@ type NetworkParam struct {
FixedIp string `json:"fixed_ip,omitempty"`
// Filters for optional network query
Filter Filter `json:"filter,omitempty"`
// Subnet within a network to use
SubnetID string `json:"subnet_id,omitempty"`
}

type Filter struct {
Expand Down
59 changes: 44 additions & 15 deletions pkg/cloud/openstack/clients/machineservice.go
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
"github.com/gophercloud/gophercloud/pagination"
"github.com/gophercloud/utils/openstack/clientconfig"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -67,6 +68,10 @@ type Instance struct {
servers.Server
}

type ServerNetwork struct {
networkID string
subnetID string
}
type InstanceListOpts struct {
// Name of the image in URL format.
Image string `q:"image"`
Expand Down Expand Up @@ -254,6 +259,22 @@ func getNetworkIDsByFilter(is *InstanceService, opts *networks.ListOpts) ([]stri
return uuids, nil
}

func CreatePort(is *InstanceService, name string, net ServerNetwork, securityGroups *[]string) (ports.Port, error) {
portCreateOpts := ports.CreateOpts{
Name: name,
NetworkID: net.networkID,
SecurityGroups: securityGroups,
}
if net.subnetID != "" {
portCreateOpts.FixedIPs = []ports.IP{{SubnetID: net.subnetID}}
}
newPort, err := ports.Create(is.networkClient, portCreateOpts).Extract()
if err != nil {
return ports.Port{}, fmt.Errorf("Create port for server err: %v", err)
}
return *newPort, nil
}

func (is *InstanceService) InstanceCreate(clusterName string, name string, config *openstackconfigv1.OpenstackProviderSpec, cmd string, keyName string) (instance *Instance, err error) {
if config == nil {
return nil, fmt.Errorf("create Options need be specified to create instace")
Expand All @@ -271,22 +292,33 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, confi
"cluster-api-provider-openstack",
clusterName,
}
var nets []servers.Network
// Get all network UUIDs
var nets []ServerNetwork
for _, net := range config.Networks {
if net.UUID == "" {
if net.UUID == "" && net.SubnetID == "" {
opts := networks.ListOpts(net.Filter)
ids, err := getNetworkIDsByFilter(is, &opts)
if err != nil {
return nil, err
}
for _, netID := range ids {
nets = append(nets, servers.Network{
UUID: netID,
nets = append(nets, ServerNetwork{
networkID: netID,
})
}
} else if net.UUID == "" && net.SubnetID != "" {
subnet, err := subnets.Get(is.networkClient, net.SubnetID).Extract()
if err != nil {
return nil, err
}
nets = append(nets, ServerNetwork{
networkID: subnet.NetworkID,
subnetID: net.SubnetID,
})
} else {
nets = append(nets, servers.Network{
UUID: net.UUID,
nets = append(nets, ServerNetwork{
networkID: net.UUID,
subnetID: net.SubnetID,
})
}
if len(net.Filter.Tags) > 0 {
Expand All @@ -296,9 +328,12 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, confi
userData := base64.StdEncoding.EncodeToString([]byte(cmd))
var ports_list []servers.Network
for _, net := range nets {
if net.networkID == "" {
return nil, fmt.Errorf("No network was found or provided. Please check your machine configuration and try again")
}
allPages, err := ports.List(is.networkClient, ports.ListOpts{
Name: name,
NetworkID: net.UUID,
NetworkID: net.networkID,
}).AllPages()
if err != nil {
return nil, fmt.Errorf("Searching for existing port for server err: %v", err)
Expand All @@ -310,16 +345,10 @@ func (is *InstanceService) InstanceCreate(clusterName string, name string, confi
var port ports.Port
if len(portList) == 0 {
// create server port
portCreateOpts := ports.CreateOpts{
Name: name,
NetworkID: net.UUID,
SecurityGroups: &config.SecurityGroups,
}
newPort, err := ports.Create(is.networkClient, portCreateOpts).Extract()
port, err = CreatePort(is, name, net, &config.SecurityGroups)
if err != nil {
return nil, fmt.Errorf("Create port for server err: %v", err)
return nil, fmt.Errorf("Failed to create port err: %v", err)
}
port = *newPort
} else {
port = portList[0]
}
Expand Down

0 comments on commit 38d01c0

Please sign in to comment.