From bcc7b126d17e4ea9bef35734ae35c468bacdc4a5 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 13:47:07 -0700 Subject: [PATCH 01/13] Accessor methods for ChangePodNetworkAnnotation on NetNamespace ChangePodNetworkAnnotation will be processed by the SDN master controller. SDN master controller provides synchronization when manipulating vnids for namespaces. --- pkg/sdn/api/netid.go | 86 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 pkg/sdn/api/netid.go diff --git a/pkg/sdn/api/netid.go b/pkg/sdn/api/netid.go new file mode 100644 index 000000000000..8f45f346d2ef --- /dev/null +++ b/pkg/sdn/api/netid.go @@ -0,0 +1,86 @@ +package api + +// Accessor methods to annotate NetNamespace for multitenant support +import ( + "fmt" + "strings" +) + +type PodNetworkAction string + +const ( + // Maximum VXLAN Virtual Network Identifier(VNID) as per RFC#7348 + MaxVNID = uint32((1 << 24) - 1) + // VNID: 1 to 9 are internally reserved for any special cases in the future + MinVNID = uint32(10) + // VNID: 0 reserved for default namespace and can reach any network in the cluster + GlobalVNID = uint32(0) + + // ChangePodNetworkAnnotation is an annotation on NetNamespace to request change of pod network + ChangePodNetworkAnnotation string = "pod.network.openshift.io/multitenant.change-network" + + // Acceptable values for ChangePodNetworkAnnotation + GlobalPodNetwork PodNetworkAction = "global" + JoinPodNetwork PodNetworkAction = "join" + IsolatePodNetwork PodNetworkAction = "isolate" +) + +var ( + ErrorPodNetworkAnnotationNotFound = fmt.Errorf("ChangePodNetworkAnnotation not found") +) + +// Check if the given vnid is valid or not +func ValidVNID(vnid uint32) error { + if vnid == GlobalVNID { + return nil + } + if vnid < MinVNID { + return fmt.Errorf("VNID must be greater than or equal to %d", MinVNID) + } + if vnid > MaxVNID { + return fmt.Errorf("VNID must be less than or equal to %d", MaxVNID) + } + return nil +} + +// GetChangePodNetworkAnnotation fetches network change intent from NetNamespace +func GetChangePodNetworkAnnotation(netns *NetNamespace) (PodNetworkAction, string, error) { + value, ok := netns.Annotations[ChangePodNetworkAnnotation] + if !ok { + return PodNetworkAction(""), "", ErrorPodNetworkAnnotationNotFound + } + + args := strings.Split(value, ":") + switch PodNetworkAction(args[0]) { + case GlobalPodNetwork: + return GlobalPodNetwork, "", nil + case JoinPodNetwork: + if len(args) != 2 { + return PodNetworkAction(""), "", fmt.Errorf("invalid namespace for join pod network: %s", value) + } + namespace := args[1] + return JoinPodNetwork, namespace, nil + case IsolatePodNetwork: + return IsolatePodNetwork, "", nil + } + + return PodNetworkAction(""), "", fmt.Errorf("invalid ChangePodNetworkAnnotation: %s", value) +} + +// SetChangePodNetworkAnnotation sets network change intent on NetNamespace +func SetChangePodNetworkAnnotation(netns *NetNamespace, action PodNetworkAction, params string) { + if netns.Annotations == nil { + netns.Annotations = make(map[string]string) + } + + value := string(action) + if len(params) != 0 { + value = fmt.Sprintf("%s:%s", value, params) + } + netns.Annotations[ChangePodNetworkAnnotation] = value +} + +// DeleteChangePodNetworkAnnotation removes network change intent from NetNamespace +func DeleteChangePodNetworkAnnotation(netns *NetNamespace) { + delete(netns.Annotations, ChangePodNetworkAnnotation) +} From f9b17b1aae1db8738ed7b3b376276ad108a34d99 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 14:34:12 -0700 Subject: [PATCH 02/13] Added network ID range interface --- pkg/sdn/plugin/netid/netid.go | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 pkg/sdn/plugin/netid/netid.go diff --git a/pkg/sdn/plugin/netid/netid.go b/pkg/sdn/plugin/netid/netid.go new file mode 100644 index 000000000000..6445e033d01b --- /dev/null +++ b/pkg/sdn/plugin/netid/netid.go @@ -0,0 +1,53 @@ +package netid + +import ( + "fmt" + + "github.com/openshift/origin/pkg/sdn/api" +) + +type NetIDRange struct { + Base uint32 + Size uint32 +} + +// Contains tests whether a given netid falls within the Range. +func (r *NetIDRange) Contains(netid uint32) (bool, uint32) { + if (netid >= r.Base) && ((netid - r.Base) < r.Size) { + offset := netid - r.Base + return true, offset + } + return false, 0 +} + +func (r *NetIDRange) String() string { + if r.Size == 0 { + return "" + } + return fmt.Sprintf("%d-%d", r.Base, r.Base+r.Size-1) +} + +func (r *NetIDRange) Set(base, size uint32) error { + if base < api.MinVNID { + return fmt.Errorf("invalid netid base, must be greater than %d", api.MinVNID) + } + if size == 0 { + return fmt.Errorf("invalid netid size, must be greater than zero") + } + if (base + size - 1) > api.MaxVNID { + return fmt.Errorf("netid range exceeded max value %d", api.MaxVNID) + } + + r.Base = base + r.Size = size + return nil +} + +func NewNetIDRange(min, max uint32) (*NetIDRange, error) { + r := &NetIDRange{} + err := r.Set(min, max-min+1) + if err != nil { + return nil, err + } + return r, nil +} From 624996b619450b3a68fa96f7e02c77541a30ad10 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 14:34:41 -0700 Subject: [PATCH 03/13] Test cases for network ID range interface --- pkg/sdn/plugin/netid/netid_test.go | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pkg/sdn/plugin/netid/netid_test.go diff --git a/pkg/sdn/plugin/netid/netid_test.go b/pkg/sdn/plugin/netid/netid_test.go new file mode 100644 index 000000000000..2245902476b6 --- /dev/null +++ b/pkg/sdn/plugin/netid/netid_test.go @@ -0,0 +1,49 @@ +package netid + +import ( + "testing" +) + +func TestNetIDRange(t *testing.T) { + testCases := []struct { + min uint32 + max uint32 + success bool + expected string + included int + excluded int + usecase string + }{ + {101, 200, true, "101-200", 150, 201, "valid input"}, + {201, 300, true, "201-300", 201, 301, "valid input, check min"}, + {201, 300, true, "201-300", 300, 301, "valid input, check max"}, + {10, 10, true, "10-10", 10, 11, "input with size=1"}, + {100, 99, false, "", -1, -1, "invalid size"}, + {1, 100, false, "", -1, -1, "invalid min"}, + {1, (1 << 25), false, "", -1, -1, "invalid max"}, + } + + for i := range testCases { + tc := &testCases[i] + r, err := NewNetIDRange(tc.min, tc.max) + if err != nil && tc.success == true { + t.Errorf("expected success for %s, got %q", tc.usecase, err) + continue + } else if err == nil && tc.success == false { + t.Errorf("expected failure for %s", tc.usecase) + continue + } else if tc.success { + if r.String() != tc.expected { + t.Errorf("expected %q, got %q", tc.expected, r.String()) + } + ok, _ := r.Contains(uint32(tc.included)) + if tc.included >= 0 && !ok { + t.Errorf("expected %q to include %d", r.String(), tc.included) + } + ok, _ = r.Contains(uint32(tc.excluded)) + if tc.excluded >= 0 && ok { + t.Errorf("expected %q to exclude %d", r.String(), tc.excluded) + } + } + } +} From 8b7b5405352c17b70ba70bef424f102e336a4ba1 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 14:35:03 -0700 Subject: [PATCH 04/13] Added network ID allocator interface --- pkg/sdn/plugin/netid/allocator.go | 103 ++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 pkg/sdn/plugin/netid/allocator.go diff --git a/pkg/sdn/plugin/netid/allocator.go b/pkg/sdn/plugin/netid/allocator.go new file mode 100644 index 000000000000..1879779cd511 --- /dev/null +++ b/pkg/sdn/plugin/netid/allocator.go @@ -0,0 +1,103 @@ +package netid + +import ( + "errors" + + "k8s.io/kubernetes/pkg/registry/service/allocator" +) + +// Interface manages the allocation of netids out of a range. +// Interface should be threadsafe. +type Interface interface { + Allocate(uint32) error + AllocateNext() (uint32, error) + Release(uint32) error + Has(uint32) bool +} + +var ( + ErrFull = errors.New("range is full") + ErrNotInRange = errors.New("provided netid is not in the valid range") + ErrAllocated = errors.New("provided netid is already allocated") +) + +type Allocator struct { + netIDRange *NetIDRange + alloc allocator.Interface +} + +// Allocator implements allocator Interface +var _ Interface = &Allocator{} + +// New creates a Allocator over a netid Range, calling allocatorFactory to construct the backing store. +func New(r *NetIDRange, allocatorFactory allocator.AllocatorFactory) *Allocator { + return &Allocator{ + netIDRange: r, + alloc: allocatorFactory(int(r.Size), r.String()), + } +} + +// Helper that wraps New, for creating a range backed by an in-memory store. +func NewInMemory(r *NetIDRange) *Allocator { + return New(r, func(max int, rangeSpec string) allocator.Interface { + return allocator.NewAllocationMap(max, rangeSpec) + }) +} + +// Free returns the count of netid left in the range. +func (r *Allocator) Free() int { + return r.alloc.Free() +} + +// Allocate attempts to reserve the provided netid. ErrNotInRange or +// ErrAllocated will be returned if the netid is not valid for this range +// or has already been reserved. +func (r *Allocator) Allocate(id uint32) error { + ok, offset := r.netIDRange.Contains(id) + if !ok { + return ErrNotInRange + } + + allocated, err := r.alloc.Allocate(int(offset)) + if err != nil { + return err + } + if !allocated { + return ErrAllocated + } + return nil +} + +// AllocateNext reserves one of the netids from the pool. ErrFull may +// be returned if there are no netids left. +func (r *Allocator) AllocateNext() (uint32, error) { + offset, ok, err := r.alloc.AllocateNext() + if err != nil { + return 0, err + } + if !ok { + return 0, ErrFull + } + return r.netIDRange.Base + uint32(offset), nil +} + +// Release releases the netid back to the pool. Releasing an +// unallocated netid or a netid out of the range is a no-op and +// returns no error. +func (r *Allocator) Release(id uint32) error { + ok, offset := r.netIDRange.Contains(id) + if !ok { + return nil + } + return r.alloc.Release(int(offset)) +} + +// Has returns true if the provided netid is already allocated and a call +// to Allocate(netid) would fail with ErrAllocated. +func (r *Allocator) Has(id uint32) bool { + ok, offset := r.netIDRange.Contains(id) + if !ok { + return false + } + return r.alloc.Has(int(offset)) +} From 282f30d2d421b4bbf865eef7c84ce349006fcdef Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 14:35:28 -0700 Subject: [PATCH 05/13] Test cases for network ID allocator interface --- pkg/sdn/plugin/netid/allocator_test.go | 86 ++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 pkg/sdn/plugin/netid/allocator_test.go diff --git a/pkg/sdn/plugin/netid/allocator_test.go b/pkg/sdn/plugin/netid/allocator_test.go new file mode 100644 index 000000000000..6b28ca33292d --- /dev/null +++ b/pkg/sdn/plugin/netid/allocator_test.go @@ -0,0 +1,86 @@ +package netid + +import ( + "strconv" + "testing" + + "k8s.io/kubernetes/pkg/util/sets" +) + +func TestAllocate(t *testing.T) { + nr, err := NewNetIDRange(201, 300) + if err != nil { + t.Fatal(err) + } + r := NewInMemory(nr) + if f := r.Free(); f != 100 { + t.Errorf("unexpected free %d", f) + } + + // Test AllocateNext() + found := sets.NewString() + count := 0 + for r.Free() > 0 { + netid, err := r.AllocateNext() + if err != nil { + t.Fatalf("error @ %d: %v", count, err) + } + count++ + if ok, _ := nr.Contains(netid); !ok { + t.Fatalf("allocated %d which is outside of %v", netid, nr) + } + netidString := strconv.Itoa(int(netid)) + if found.Has(netidString) { + t.Fatalf("allocated %d twice @ %d", netid, count) + } + found.Insert(netidString) + } + if count != 100 { + t.Fatal("failed to allocate all netids in the given range") + } + if _, err := r.AllocateNext(); err != ErrFull { + t.Fatal(err) + } + + // Test Release() + released := uint32(210) + if err := r.Release(released); err != nil { + t.Fatal(err) + } + if f := r.Free(); f != 1 { + t.Errorf("unexpected free %d", f) + } + netid, err := r.AllocateNext() + if err != nil { + t.Fatal(err) + } + if released != netid { + t.Errorf("unexpected %d : %d", netid, released) + } + + // Test Allocate() + if err := r.Release(released); err != nil { + t.Fatal(err) + } + if err := r.Allocate(1); err != ErrNotInRange { + t.Fatal(err) + } + if err := r.Allocate(201); err != ErrAllocated { + t.Fatal(err) + } + if err := r.Allocate(301); err != ErrNotInRange { + t.Fatal(err) + } + if err := r.Allocate(500); err != ErrNotInRange { + t.Fatal(err) + } + if f := r.Free(); f != 1 { + t.Errorf("unexpected free %d", f) + } + if err := r.Allocate(released); err != nil { + t.Fatal(err) + } + if f := r.Free(); f != 0 { + t.Errorf("unexpected free %d", f) + } +} From e0621a7aae1ada324be81839016e7d86618e0500 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 14:41:43 -0700 Subject: [PATCH 06/13] Handling VNID manipulations - Split vnids.go based on master and node roles - Use netID allocator interface (bitmap instead of integer map) - Use ChangePodNetworkAnnotation on NetNamespace for VNID manipulation - Synchronize add/delete/update VNID operations - Added support for exposing project network isolation --- pkg/sdn/api/validation/validation.go | 11 +- pkg/sdn/plugin/master.go | 11 +- pkg/sdn/plugin/node.go | 4 +- pkg/sdn/plugin/registry.go | 6 +- pkg/sdn/plugin/vnids_master.go | 324 ++++++++++++++++++ pkg/sdn/plugin/{vnids.go => vnids_node.go} | 231 ++----------- .../{vnids_test.go => vnids_node_test.go} | 76 ++-- 7 files changed, 420 insertions(+), 243 deletions(-) create mode 100644 pkg/sdn/plugin/vnids_master.go rename pkg/sdn/plugin/{vnids.go => vnids_node.go} (54%) rename pkg/sdn/plugin/{vnids_test.go => vnids_node_test.go} (73%) diff --git a/pkg/sdn/api/validation/validation.go b/pkg/sdn/api/validation/validation.go index acf81017b8bc..65780fdb85c4 100644 --- a/pkg/sdn/api/validation/validation.go +++ b/pkg/sdn/api/validation/validation.go @@ -108,14 +108,19 @@ func ValidateHostSubnetUpdate(obj *sdnapi.HostSubnet, old *sdnapi.HostSubnet) fi func ValidateNetNamespace(netnamespace *sdnapi.NetNamespace) field.ErrorList { allErrs := validation.ValidateObjectMeta(&netnamespace.ObjectMeta, false, oapi.MinimalNameRequirements, field.NewPath("metadata")) - if netnamespace.NetID < 0 { - allErrs = append(allErrs, field.Invalid(field.NewPath("netID"), netnamespace.NetID, "invalid Net ID: cannot be negative")) + if err := sdnapi.ValidVNID(netnamespace.NetID); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("netID"), netnamespace.NetID, err.Error())) } return allErrs } func ValidateNetNamespaceUpdate(obj *sdnapi.NetNamespace, old *sdnapi.NetNamespace) field.ErrorList { - return validation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata")) + allErrs := validation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata")) + + if err := sdnapi.ValidVNID(obj.NetID); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("netID"), obj.NetID, err.Error())) + } + return allErrs } // ValidateEgressNetworkPolicy tests if required fields in the EgressNetworkPolicy are set. diff --git a/pkg/sdn/plugin/master.go b/pkg/sdn/plugin/master.go index 7365597f3d01..37b95686dc9c 100644 --- a/pkg/sdn/plugin/master.go +++ b/pkg/sdn/plugin/master.go @@ -17,9 +17,7 @@ import ( type OsdnMaster struct { registry *Registry subnetAllocator *netutils.SubnetAllocator - vnids *vnidMap - netIDManager *netutils.NetIDAllocator - adminNamespaces []string + vnids *masterVNIDMap } func StartMaster(networkConfig osconfigapi.MasterNetworkConfig, osClient *osclient.Client, kClient *kclient.Client) error { @@ -28,10 +26,9 @@ func StartMaster(networkConfig osconfigapi.MasterNetworkConfig, osClient *osclie } log.Infof("Initializing SDN master of type %q", networkConfig.NetworkPluginName) + master := &OsdnMaster{ - registry: newRegistry(osClient, kClient), - vnids: newVnidMap(), - adminNamespaces: make([]string, 0), + registry: newRegistry(osClient, kClient), } // Validate command-line/config parameters @@ -59,6 +56,8 @@ func StartMaster(networkConfig osconfigapi.MasterNetworkConfig, osClient *osclie } if IsOpenShiftMultitenantNetworkPlugin(networkConfig.NetworkPluginName) { + master.vnids = newMasterVNIDMap() + if err = master.VnidStartMaster(); err != nil { return err } diff --git a/pkg/sdn/plugin/node.go b/pkg/sdn/plugin/node.go index bdca07feb1f4..cbf856d3bc32 100644 --- a/pkg/sdn/plugin/node.go +++ b/pkg/sdn/plugin/node.go @@ -27,7 +27,7 @@ type OsdnNode struct { localSubnet *osapi.HostSubnet hostName string podNetworkReady chan struct{} - vnids *vnidMap + vnids *nodeVNIDMap iptablesSyncPeriod time.Duration mtu uint32 egressPolicies map[uint32][]*osapi.EgressNetworkPolicy @@ -68,7 +68,7 @@ func NewNodePlugin(pluginName string, osClient *osclient.Client, kClient *kclien registry: newRegistry(osClient, kClient), localIP: selfIP, hostName: hostname, - vnids: newVnidMap(), + vnids: newNodeVNIDMap(), podNetworkReady: make(chan struct{}), iptablesSyncPeriod: iptablesSyncPeriod, mtu: mtu, diff --git a/pkg/sdn/plugin/registry.go b/pkg/sdn/plugin/registry.go index 4aa3b8b45c38..2af744190d78 100644 --- a/pkg/sdn/plugin/registry.go +++ b/pkg/sdn/plugin/registry.go @@ -212,7 +212,7 @@ func (registry *Registry) GetNetNamespace(name string) (*osapi.NetNamespace, err return registry.oClient.NetNamespaces().Get(name) } -func (registry *Registry) WriteNetNamespace(name string, id uint32) error { +func (registry *Registry) CreateNetNamespace(name string, id uint32) error { netns := &osapi.NetNamespace{ TypeMeta: unversioned.TypeMeta{Kind: "NetNamespace"}, ObjectMeta: kapi.ObjectMeta{Name: name}, @@ -223,6 +223,10 @@ func (registry *Registry) WriteNetNamespace(name string, id uint32) error { return err } +func (registry *Registry) UpdateNetNamespace(netns *osapi.NetNamespace) (*osapi.NetNamespace, error) { + return registry.oClient.NetNamespaces().Update(netns) +} + func (registry *Registry) DeleteNetNamespace(name string) error { return registry.oClient.NetNamespaces().Delete(name) } diff --git a/pkg/sdn/plugin/vnids_master.go b/pkg/sdn/plugin/vnids_master.go new file mode 100644 index 000000000000..e350e8b0cd0c --- /dev/null +++ b/pkg/sdn/plugin/vnids_master.go @@ -0,0 +1,324 @@ +package plugin + +import ( + "fmt" + "strings" + "sync" + + log "github.com/golang/glog" + + kapi "k8s.io/kubernetes/pkg/api" + utilruntime "k8s.io/kubernetes/pkg/util/runtime" + "k8s.io/kubernetes/pkg/util/sets" + utilwait "k8s.io/kubernetes/pkg/util/wait" + "k8s.io/kubernetes/pkg/watch" + + osapi "github.com/openshift/origin/pkg/sdn/api" + pnetid "github.com/openshift/origin/pkg/sdn/plugin/netid" +) + +type masterVNIDMap struct { + // Synchronizes assign, revoke and update VNID + lock sync.Mutex + ids map[string]uint32 + netIDManager *pnetid.Allocator + + adminNamespaces sets.String +} + +func newMasterVNIDMap() *masterVNIDMap { + netIDRange, err := pnetid.NewNetIDRange(osapi.MinVNID, osapi.MaxVNID) + if err != nil { + panic(err) + } + + return &masterVNIDMap{ + netIDManager: pnetid.NewInMemory(netIDRange), + adminNamespaces: sets.NewString(kapi.NamespaceDefault), + ids: make(map[string]uint32), + } +} + +func (vmap *masterVNIDMap) getVNID(name string) (uint32, bool) { + id, found := vmap.ids[name] + return id, found +} + +func (vmap *masterVNIDMap) setVNID(name string, id uint32) { + vmap.ids[name] = id +} + +func (vmap *masterVNIDMap) unsetVNID(name string) (uint32, bool) { + id, found := vmap.ids[name] + delete(vmap.ids, name) + return id, found +} + +func (vmap *masterVNIDMap) getVNIDCount(id uint32) int { + count := 0 + for _, netid := range vmap.ids { + if id == netid { + count = count + 1 + } + } + return count +} + +func (vmap *masterVNIDMap) isAdminNamespace(nsName string) bool { + if vmap.adminNamespaces.Has(nsName) { + return true + } + return false +} + +func (vmap *masterVNIDMap) populateVNIDs(registry *Registry) error { + netnsList, err := registry.GetNetNamespaces() + if err != nil { + return err + } + + for _, netns := range netnsList { + vmap.setVNID(netns.NetName, netns.NetID) + + // Skip GlobalVNID, not part of netID allocation range + if netns.NetID == osapi.GlobalVNID { + continue + } + + switch err := vmap.netIDManager.Allocate(netns.NetID); err { + case nil: // Expected normal case + case pnetid.ErrAllocated: // Expected when project networks are joined + default: + return fmt.Errorf("unable to allocate netid %d: %v", netns.NetID, err) + } + } + return nil +} + +func (vmap *masterVNIDMap) allocateNetID(nsName string) (uint32, bool, error) { + // Nothing to do if the netid is in the vnid map + exists := false + if netid, found := vmap.getVNID(nsName); found { + exists = true + return netid, exists, nil + } + + // NetNamespace not found, so allocate new NetID + var netid uint32 + if vmap.isAdminNamespace(nsName) { + netid = osapi.GlobalVNID + } else { + var err error + netid, err = vmap.netIDManager.AllocateNext() + if err != nil { + return 0, exists, err + } + } + + vmap.setVNID(nsName, netid) + log.Infof("Allocated netid %d for namespace %q", netid, nsName) + return netid, exists, nil +} + +func (vmap *masterVNIDMap) releaseNetID(nsName string) error { + // Remove NetID from vnid map + netid, found := vmap.unsetVNID(nsName) + if !found { + return fmt.Errorf("netid not found for namespace %q", nsName) + } + + // Skip osapi.GlobalVNID as it is not part of NetID allocation + if netid == osapi.GlobalVNID { + return nil + } + + // Check if this netid is used by any other namespaces + // If not, then release the netid + if count := vmap.getVNIDCount(netid); count == 0 { + if err := vmap.netIDManager.Release(netid); err != nil { + return fmt.Errorf("Error while releasing netid %d for namespace %q, %v", netid, nsName, err) + } + log.Infof("Released netid %d for namespace %q", netid, nsName) + } else { + log.V(5).Infof("netid %d for namespace %q is still in use", netid, nsName) + } + return nil +} + +func (vmap *masterVNIDMap) updateNetID(nsName string, action osapi.PodNetworkAction, args string) (uint32, error) { + var netid uint32 + allocated := false + + // Check if the given namespace exists or not + oldnetid, found := vmap.getVNID(nsName) + if !found { + return 0, fmt.Errorf("netid not found for namespace %q", nsName) + } + + // Determine new network ID + switch action { + case osapi.GlobalPodNetwork: + netid = osapi.GlobalVNID + case osapi.JoinPodNetwork: + joinNsName := args + var found bool + if netid, found = vmap.getVNID(joinNsName); !found { + return 0, fmt.Errorf("netid not found for namespace %q", joinNsName) + } + case osapi.IsolatePodNetwork: + // Check if the given namespace is already isolated + if count := vmap.getVNIDCount(oldnetid); count == 1 { + return oldnetid, nil + } + + var err error + netid, err = vmap.netIDManager.AllocateNext() + if err != nil { + return 0, err + } + allocated = true + default: + return 0, fmt.Errorf("invalid pod network action: %v", action) + } + + // Release old network ID + if err := vmap.releaseNetID(nsName); err != nil { + if allocated { + vmap.netIDManager.Release(netid) + } + return 0, err + } + + // Set new network ID + vmap.setVNID(nsName, netid) + log.Infof("Updated netid %d for namespace %q", netid, nsName) + return netid, nil +} + +// assignVNID, revokeVNID and updateVNID methods updates in-memory structs and persists etcd objects +func (vmap *masterVNIDMap) assignVNID(registry *Registry, nsName string) error { + vmap.lock.Lock() + defer vmap.lock.Unlock() + + netid, exists, err := vmap.allocateNetID(nsName) + if err != nil { + return err + } + + if !exists { + // Create NetNamespace Object and update vnid map + err = registry.CreateNetNamespace(nsName, netid) + if err != nil { + vmap.releaseNetID(nsName) + return err + } + } + return nil +} + +func (vmap *masterVNIDMap) revokeVNID(registry *Registry, nsName string) error { + vmap.lock.Lock() + defer vmap.lock.Unlock() + + // Delete NetNamespace object + if err := registry.DeleteNetNamespace(nsName); err != nil { + return err + } + + if err := vmap.releaseNetID(nsName); err != nil { + return err + } + return nil +} + +func (vmap *masterVNIDMap) updateVNID(registry *Registry, netns *osapi.NetNamespace) error { + action, args, err := osapi.GetChangePodNetworkAnnotation(netns) + if err == osapi.ErrorPodNetworkAnnotationNotFound { + // Nothing to update + return nil + } + + vmap.lock.Lock() + defer vmap.lock.Unlock() + + netid, err := vmap.updateNetID(netns.NetName, action, args) + if err != nil { + return err + } + netns.NetID = netid + osapi.DeleteChangePodNetworkAnnotation(netns) + + if _, err := registry.UpdateNetNamespace(netns); err != nil { + return err + } + return nil +} + +//--------------------- Master methods ---------------------- + +func (master *OsdnMaster) VnidStartMaster() error { + err := master.vnids.populateVNIDs(master.registry) + if err != nil { + return err + } + + go utilwait.Forever(master.watchNamespaces, 0) + go utilwait.Forever(master.watchNetNamespaces, 0) + return nil +} + +func (master *OsdnMaster) watchNamespaces() { + registry := master.registry + eventQueue := registry.RunEventQueue(Namespaces) + + for { + eventType, obj, err := eventQueue.Pop() + if err != nil { + utilruntime.HandleError(fmt.Errorf("EventQueue failed for namespaces: %v", err)) + return + } + ns := obj.(*kapi.Namespace) + name := ns.ObjectMeta.Name + + log.V(5).Infof("Watch %s event for Namespace %q", strings.Title(string(eventType)), name) + switch eventType { + case watch.Added, watch.Modified: + err = master.vnids.assignVNID(registry, name) + if err != nil { + log.Errorf("Error assigning netid: %v", err) + continue + } + case watch.Deleted: + err = master.vnids.revokeVNID(registry, name) + if err != nil { + log.Errorf("Error revoking netid: %v", err) + continue + } + } + } +} + +func (master *OsdnMaster) watchNetNamespaces() { + registry := master.registry + eventQueue := registry.RunEventQueue(NetNamespaces) + + for { + eventType, obj, err := eventQueue.Pop() + if err != nil { + utilruntime.HandleError(fmt.Errorf("EventQueue failed for network namespaces: %v", err)) + return + } + netns := obj.(*osapi.NetNamespace) + name := netns.ObjectMeta.Name + + log.V(5).Infof("Watch %s event for NetNamespace %q", strings.Title(string(eventType)), name) + switch eventType { + case watch.Added, watch.Modified: + err = master.vnids.updateVNID(registry, netns) + if err != nil { + log.Errorf("Error updating netid: %v", err) + continue + } + } + } +} diff --git a/pkg/sdn/plugin/vnids.go b/pkg/sdn/plugin/vnids_node.go similarity index 54% rename from pkg/sdn/plugin/vnids.go rename to pkg/sdn/plugin/vnids_node.go index 123a07a92f65..a457cdc51076 100644 --- a/pkg/sdn/plugin/vnids.go +++ b/pkg/sdn/plugin/vnids_node.go @@ -17,30 +17,23 @@ import ( "k8s.io/kubernetes/pkg/watch" osapi "github.com/openshift/origin/pkg/sdn/api" - "github.com/openshift/origin/pkg/util/netutils" ) -const ( - // Maximum VXLAN Network Identifier as per RFC#7348 - MaxVNID = uint32((1 << 24) - 1) - // VNID for the admin namespaces - AdminVNID = uint32(0) -) - -type vnidMap struct { +type nodeVNIDMap struct { + // Synchronizes add or remove ids/namespaces + lock sync.Mutex ids map[string]uint32 namespaces map[uint32]sets.String - lock sync.Mutex } -func newVnidMap() *vnidMap { - return &vnidMap{ +func newNodeVNIDMap() *nodeVNIDMap { + return &nodeVNIDMap{ ids: make(map[string]uint32), namespaces: make(map[uint32]sets.String), } } -func (vmap *vnidMap) addNamespaceToSet(name string, vnid uint32) { +func (vmap *nodeVNIDMap) addNamespaceToSet(name string, vnid uint32) { set, found := vmap.namespaces[vnid] if !found { set = sets.NewString() @@ -49,7 +42,7 @@ func (vmap *vnidMap) addNamespaceToSet(name string, vnid uint32) { set.Insert(name) } -func (vmap *vnidMap) removeNamespaceFromSet(name string, vnid uint32) { +func (vmap *nodeVNIDMap) removeNamespaceFromSet(name string, vnid uint32) { if set, found := vmap.namespaces[vnid]; found { set.Delete(name) if set.Len() == 0 { @@ -58,15 +51,25 @@ func (vmap *vnidMap) removeNamespaceFromSet(name string, vnid uint32) { } } -func (vmap *vnidMap) GetVNID(name string) (uint32, error) { +func (vmap *nodeVNIDMap) GetNamespaces(id uint32) []string { + vmap.lock.Lock() + defer vmap.lock.Unlock() + + if set, ok := vmap.namespaces[id]; ok { + return set.List() + } else { + return nil + } +} + +func (vmap *nodeVNIDMap) GetVNID(name string) (uint32, error) { vmap.lock.Lock() defer vmap.lock.Unlock() if id, ok := vmap.ids[name]; ok { return id, nil } - // In case of error, return some value which is not a valid VNID - return uint32(MaxVNID + 1), fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) + return 0, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) } // Nodes asynchronously watch for both NetNamespaces and services @@ -75,7 +78,7 @@ func (vmap *vnidMap) GetVNID(name string) (uint32, error) { // and if service/pod-setup tries to lookup vnid map then it may fail. // So, use this method to alleviate this problem. This method will // retry vnid lookup before giving up. -func (vmap *vnidMap) WaitAndGetVNID(name string) (uint32, error) { +func (vmap *nodeVNIDMap) WaitAndGetVNID(name string) (uint32, error) { // Try few times up to 2 seconds retries := 20 retryInterval := 100 * time.Millisecond @@ -86,22 +89,10 @@ func (vmap *vnidMap) WaitAndGetVNID(name string) (uint32, error) { time.Sleep(retryInterval) } - // In case of error, return some value which is not a valid VNID - return MaxVNID + 1, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) + return 0, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) } -func (vmap *vnidMap) GetNamespaces(id uint32) []string { - vmap.lock.Lock() - defer vmap.lock.Unlock() - - if set, ok := vmap.namespaces[id]; ok { - return set.List() - } else { - return nil - } -} - -func (vmap *vnidMap) SetVNID(name string, id uint32) { +func (vmap *nodeVNIDMap) setVNID(name string, id uint32) { vmap.lock.Lock() defer vmap.lock.Unlock() @@ -114,14 +105,13 @@ func (vmap *vnidMap) SetVNID(name string, id uint32) { log.Infof("Associate netid %d to namespace %q", id, name) } -func (vmap *vnidMap) UnsetVNID(name string) (id uint32, err error) { +func (vmap *nodeVNIDMap) unsetVNID(name string) (id uint32, err error) { vmap.lock.Lock() defer vmap.lock.Unlock() id, found := vmap.ids[name] if !found { - // In case of error, return some value which is not a valid VNID - return MaxVNID + 1, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) + return 0, fmt.Errorf("Failed to find netid for namespace: %s in vnid map", name) } vmap.removeNamespaceFromSet(name, id) delete(vmap.ids, name) @@ -129,178 +119,23 @@ func (vmap *vnidMap) UnsetVNID(name string) (id uint32, err error) { return id, nil } -func (vmap *vnidMap) CheckVNID(id uint32) bool { - vmap.lock.Lock() - defer vmap.lock.Unlock() - - _, found := vmap.namespaces[id] - return found -} - -func (vmap *vnidMap) GetAllocatedVNIDs() []uint32 { - vmap.lock.Lock() - defer vmap.lock.Unlock() - - ids := []uint32{} - idSet := sets.Int{} - for _, id := range vmap.ids { - if id != AdminVNID { - if !idSet.Has(int(id)) { - ids = append(ids, id) - idSet.Insert(int(id)) - } - } - } - return ids -} - -func (vmap *vnidMap) PopulateVNIDs(registry *Registry) error { +func (vmap *nodeVNIDMap) populateVNIDs(registry *Registry) error { nets, err := registry.GetNetNamespaces() if err != nil { return err } for _, net := range nets { - vmap.SetVNID(net.Name, net.NetID) + vmap.setVNID(net.Name, net.NetID) } return nil } -func (master *OsdnMaster) VnidStartMaster() error { - err := master.vnids.PopulateVNIDs(master.registry) - if err != nil { - return err - } - - // VNID: 0 reserved for default namespace and can reach any network in the cluster - // VNID: 1 to 9 are internally reserved for any special cases in the future - master.netIDManager, err = netutils.NewNetIDAllocator(10, MaxVNID, master.vnids.GetAllocatedVNIDs()) - if err != nil { - return err - } - - // 'default' namespace is currently always an admin namespace - master.adminNamespaces = append(master.adminNamespaces, "default") - - go utilwait.Forever(master.watchNamespaces, 0) - return nil -} - -func (master *OsdnMaster) isAdminNamespace(nsName string) bool { - for _, name := range master.adminNamespaces { - if name == nsName { - return true - } - } - return false -} - -func (master *OsdnMaster) assignVNID(namespaceName string) error { - // Nothing to do if the netid is in the vnid map - if _, err := master.vnids.GetVNID(namespaceName); err == nil { - return nil - } - - // If NetNamespace is present, update vnid map - netns, err := master.registry.GetNetNamespace(namespaceName) - if err == nil { - master.vnids.SetVNID(namespaceName, netns.NetID) - return nil - } - - // NetNamespace not found, so allocate new NetID - var netid uint32 - if master.isAdminNamespace(namespaceName) { - netid = AdminVNID - } else { - netid, err = master.netIDManager.GetNetID() - if err != nil { - return err - } - } - - // Create NetNamespace Object and update vnid map - err = master.registry.WriteNetNamespace(namespaceName, netid) - if err != nil { - e := master.netIDManager.ReleaseNetID(netid) - if e != nil { - log.Errorf("Error while releasing netid: %v", e) - } - return err - } - master.vnids.SetVNID(namespaceName, netid) - return nil -} - -func (master *OsdnMaster) revokeVNID(namespaceName string) error { - // Remove NetID from vnid map - netid_found := true - netid, err := master.vnids.UnsetVNID(namespaceName) - if err != nil { - log.Error(err) - netid_found = false - } - - // Delete NetNamespace object - err = master.registry.DeleteNetNamespace(namespaceName) - if err != nil { - return err - } - - // Skip NetID release if - // - Value matches AdminVNID as it is not part of NetID allocation or - // - NetID is not found in the vnid map - if (netid == AdminVNID) || !netid_found { - return nil - } - - // Check if this netid is used by any other namespaces - // If not, then release the netid - if !master.vnids.CheckVNID(netid) { - err = master.netIDManager.ReleaseNetID(netid) - if err != nil { - return fmt.Errorf("Error while releasing netid %d for namespace %q, %v", netid, namespaceName, err) - } - log.Infof("Released netid %d for namespace %q", netid, namespaceName) - } else { - log.V(5).Infof("netid %d for namespace %q is still in use", netid, namespaceName) - } - return nil -} - -func (master *OsdnMaster) watchNamespaces() { - eventQueue := master.registry.RunEventQueue(Namespaces) - - for { - eventType, obj, err := eventQueue.Pop() - if err != nil { - utilruntime.HandleError(fmt.Errorf("EventQueue failed for namespaces: %v", err)) - return - } - ns := obj.(*kapi.Namespace) - name := ns.ObjectMeta.Name - - log.V(5).Infof("Watch %s event for Namespace %q", strings.Title(string(eventType)), name) - switch eventType { - case watch.Added, watch.Modified: - err = master.assignVNID(name) - if err != nil { - log.Errorf("Error assigning netid: %v", err) - continue - } - case watch.Deleted: - err = master.revokeVNID(name) - if err != nil { - log.Errorf("Error revoking netid: %v", err) - continue - } - } - } -} +//------------------ Node Methods -------------------- func (node *OsdnNode) VnidStartNode() error { // Populate vnid map synchronously so that existing services can fetch vnid - err := node.vnids.PopulateVNIDs(node.registry) + err := node.vnids.populateVNIDs(node.registry) if err != nil { return err } @@ -372,21 +207,21 @@ func (node *OsdnNode) watchNetNamespaces() { if (err == nil) && (oldNetID == netns.NetID) { continue } - node.vnids.SetVNID(netns.NetName, netns.NetID) + node.vnids.setVNID(netns.NetName, netns.NetID) err = node.updatePodNetwork(netns.NetName, oldNetID, netns.NetID) if err != nil { log.Errorf("Failed to update pod network for namespace '%s', error: %s", netns.NetName, err) - node.vnids.SetVNID(netns.NetName, oldNetID) + node.vnids.setVNID(netns.NetName, oldNetID) continue } case watch.Deleted: // updatePodNetwork needs vnid, so unset vnid after this call - err = node.updatePodNetwork(netns.NetName, netns.NetID, AdminVNID) + err = node.updatePodNetwork(netns.NetName, netns.NetID, osapi.GlobalVNID) if err != nil { log.Errorf("Failed to update pod network for namespace '%s', error: %s", netns.NetName, err) } - node.vnids.UnsetVNID(netns.NetName) + node.vnids.unsetVNID(netns.NetName) } } } diff --git a/pkg/sdn/plugin/vnids_test.go b/pkg/sdn/plugin/vnids_node_test.go similarity index 73% rename from pkg/sdn/plugin/vnids_test.go rename to pkg/sdn/plugin/vnids_node_test.go index 4072ddb4a3ec..1e2fba5434a9 100644 --- a/pkg/sdn/plugin/vnids_test.go +++ b/pkg/sdn/plugin/vnids_node_test.go @@ -2,10 +2,14 @@ package plugin import ( "testing" + + "k8s.io/kubernetes/pkg/util/sets" + + osapi "github.com/openshift/origin/pkg/sdn/api" ) -func TestVnidMap(t *testing.T) { - vmap := newVnidMap() +func TestNodeVNIDMap(t *testing.T) { + vmap := newNodeVNIDMap() // empty vmap @@ -15,10 +19,10 @@ func TestVnidMap(t *testing.T) { // set vnids, non-overlapping - vmap.SetVNID("alpha", 1) - vmap.SetVNID("bravo", 2) - vmap.SetVNID("charlie", 3) - vmap.SetVNID("delta", 4) + vmap.setVNID("alpha", 1) + vmap.setVNID("bravo", 2) + vmap.setVNID("charlie", 3) + vmap.setVNID("delta", 4) checkExists(t, vmap, "alpha", 1) checkExists(t, vmap, "bravo", 2) @@ -35,11 +39,11 @@ func TestVnidMap(t *testing.T) { // unset vnids - id, err := vmap.UnsetVNID("alpha") + id, err := vmap.unsetVNID("alpha") if id != 1 || err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } - id, err = vmap.UnsetVNID("charlie") + id, err = vmap.unsetVNID("charlie") if id != 3 || err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } @@ -49,11 +53,11 @@ func TestVnidMap(t *testing.T) { checkNotExists(t, vmap, "charlie") checkExists(t, vmap, "delta", 4) - id, err = vmap.UnsetVNID("alpha") + id, err = vmap.unsetVNID("alpha") if err == nil { t.Fatalf("Unexpected success: %d", id) } - id, err = vmap.UnsetVNID("echo") + id, err = vmap.unsetVNID("echo") if err == nil { t.Fatalf("Unexpected success: %d", id) } @@ -67,8 +71,8 @@ func TestVnidMap(t *testing.T) { // change vnids - vmap.SetVNID("bravo", 1) - vmap.SetVNID("delta", 2) + vmap.setVNID("bravo", 1) + vmap.setVNID("delta", 2) checkExists(t, vmap, "bravo", 1) checkExists(t, vmap, "delta", 2) @@ -82,12 +86,12 @@ func TestVnidMap(t *testing.T) { // overlapping vnids - vmap.SetVNID("echo", 3) - vmap.SetVNID("foxtrot", 5) - vmap.SetVNID("golf", 1) - vmap.SetVNID("hotel", 1) - vmap.SetVNID("india", 1) - vmap.SetVNID("juliet", 3) + vmap.setVNID("echo", 3) + vmap.setVNID("foxtrot", 5) + vmap.setVNID("golf", 1) + vmap.setVNID("hotel", 1) + vmap.setVNID("india", 1) + vmap.setVNID("juliet", 3) checkExists(t, vmap, "bravo", 1) checkExists(t, vmap, "delta", 2) @@ -108,15 +112,15 @@ func TestVnidMap(t *testing.T) { // deleting with overlapping vnids - id, err = vmap.UnsetVNID("golf") + id, err = vmap.unsetVNID("golf") if err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } - id, err = vmap.UnsetVNID("echo") + id, err = vmap.unsetVNID("echo") if err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } - id, err = vmap.UnsetVNID("juliet") + id, err = vmap.unsetVNID("juliet") if err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } @@ -137,27 +141,23 @@ func TestVnidMap(t *testing.T) { checkNamespaces(t, vmap, 5, []string{"foxtrot"}) checkAllocatedVNIDs(t, vmap, []uint32{1, 2, 5}) - } -func checkExists(t *testing.T, vmap *vnidMap, name string, expected uint32) { +func checkExists(t *testing.T, vmap *nodeVNIDMap, name string, expected uint32) { id, err := vmap.GetVNID(name) if id != expected || err != nil { t.Fatalf("Unexpected failure: %d, %v", id, err) } - if !vmap.CheckVNID(id) { - t.Fatalf("Unexpected failure") - } } -func checkNotExists(t *testing.T, vmap *vnidMap, name string) { +func checkNotExists(t *testing.T, vmap *nodeVNIDMap, name string) { id, err := vmap.GetVNID(name) if err == nil { t.Fatalf("Unexpected success: %d", id) } } -func checkNamespaces(t *testing.T, vmap *vnidMap, vnid uint32, match []string) { +func checkNamespaces(t *testing.T, vmap *nodeVNIDMap, vnid uint32, match []string) { namespaces := vmap.GetNamespaces(vnid) if len(namespaces) != len(match) { t.Fatalf("Wrong number of namespaces: %v vs %v", namespaces, match) @@ -176,14 +176,24 @@ func checkNamespaces(t *testing.T, vmap *vnidMap, vnid uint32, match []string) { } } -func checkAllocatedVNIDs(t *testing.T, vmap *vnidMap, match []uint32) { - vnids := vmap.GetAllocatedVNIDs() - if len(vnids) != len(match) { - t.Fatalf("Wrong number of VNIDs: %v vs %v", vnids, match) +func checkAllocatedVNIDs(t *testing.T, vmap *nodeVNIDMap, match []uint32) { + ids := []uint32{} + idSet := sets.Int{} + for _, id := range vmap.ids { + if id != osapi.GlobalVNID { + if !idSet.Has(int(id)) { + ids = append(ids, id) + idSet.Insert(int(id)) + } + } } + if len(ids) != len(match) { + t.Fatalf("Wrong number of VNIDs: %d vs %d", len(ids), len(match)) + } + for _, m := range match { found := false - for _, n := range vnids { + for _, n := range ids { if n == m { found = true break From 59d1aa0988f7a5ba79a5bf648e985e9584f395e2 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Thu, 11 Aug 2016 13:28:43 -0700 Subject: [PATCH 07/13] Test cases for assign/update/revoke VNIDs --- pkg/sdn/plugin/vnids_master_test.go | 100 ++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 pkg/sdn/plugin/vnids_master_test.go diff --git a/pkg/sdn/plugin/vnids_master_test.go b/pkg/sdn/plugin/vnids_master_test.go new file mode 100644 index 000000000000..4617aacb67e6 --- /dev/null +++ b/pkg/sdn/plugin/vnids_master_test.go @@ -0,0 +1,100 @@ +package plugin + +import ( + "testing" + + kapi "k8s.io/kubernetes/pkg/api" + + osapi "github.com/openshift/origin/pkg/sdn/api" +) + +func TestMasterVNIDMap(t *testing.T) { + vmap := newMasterVNIDMap() + + // empty vmap + checkCurrentVNIDs(t, vmap, 0, 0) + + // assign vnids + _, _, err := vmap.allocateNetID(kapi.NamespaceDefault) + checkNoErr(t, err) + _, exists, err := vmap.allocateNetID("alpha") + checkNoErr(t, err) + if exists { + t.Fatalf("expected netid not to exists") + } + _, exists, err = vmap.allocateNetID("alpha") + checkNoErr(t, err) + if !exists { + t.Fatalf("expected allocated netid to exists") + } + _, _, err = vmap.allocateNetID("bravo") + checkNoErr(t, err) + _, _, err = vmap.allocateNetID("charlie") + checkNoErr(t, err) + checkCurrentVNIDs(t, vmap, 4, 3) + + // update vnids + _, err = vmap.updateNetID("alpha", osapi.JoinPodNetwork, "bravo") + checkNoErr(t, err) + _, err = vmap.updateNetID("alpha", osapi.JoinPodNetwork, "bogus") + checkErr(t, err) + _, err = vmap.updateNetID("bogus", osapi.JoinPodNetwork, "alpha") + checkErr(t, err) + checkCurrentVNIDs(t, vmap, 4, 2) + + _, err = vmap.updateNetID("alpha", osapi.GlobalPodNetwork, "") + checkNoErr(t, err) + _, err = vmap.updateNetID("charlie", osapi.GlobalPodNetwork, "") + checkNoErr(t, err) + _, err = vmap.updateNetID("bogus", osapi.GlobalPodNetwork, "") + checkErr(t, err) + checkCurrentVNIDs(t, vmap, 4, 1) + + _, err = vmap.updateNetID("alpha", osapi.IsolatePodNetwork, "") + checkNoErr(t, err) + _, err = vmap.updateNetID("bravo", osapi.IsolatePodNetwork, "") + checkNoErr(t, err) + _, err = vmap.updateNetID("bogus", osapi.IsolatePodNetwork, "") + checkErr(t, err) + checkCurrentVNIDs(t, vmap, 4, 2) + + // release vnids + checkNoErr(t, vmap.releaseNetID("alpha")) + checkNoErr(t, vmap.releaseNetID("bravo")) + checkNoErr(t, vmap.releaseNetID("charlie")) + checkNoErr(t, vmap.releaseNetID(kapi.NamespaceDefault)) + checkErr(t, vmap.releaseNetID("bogus")) + checkCurrentVNIDs(t, vmap, 0, 0) +} + +func checkNoErr(t *testing.T, err error) { + if err != nil { + t.Fatal(err) + } +} + +func checkErr(t *testing.T, err error) { + if err == nil { + t.Fatalf("Expected error is missing!") + } +} + +func checkCurrentVNIDs(t *testing.T, vmap *masterVNIDMap, expectedMapCount, expectedAllocatorCount int) { + if len(vmap.ids) != expectedMapCount { + t.Fatalf("Wrong number of VNIDs: %d vs %d", len(vmap.ids), expectedMapCount) + } + + // Check bitmap allocator + expected_free := int(osapi.MaxVNID-osapi.MinVNID) + 1 - expectedAllocatorCount + if vmap.netIDManager.Free() != expected_free { + t.Fatalf("Allocator mismatch: %d vs %d", vmap.netIDManager.Free(), expected_free) + } + for _, id := range vmap.ids { + if id == osapi.GlobalVNID { + continue + } + if !vmap.netIDManager.Has(id) { + t.Fatalf("Missing VNID: %d", id) + } + } +} From 3ee1f81f0ce09de90c39ae47e9cd703aafc94a26 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 8 Aug 2016 19:02:29 -0700 Subject: [PATCH 08/13] Remove old SDN netid allocator --- pkg/util/netutils/netid_allocator.go | 54 ---------------------------- 1 file changed, 54 deletions(-) delete mode 100644 pkg/util/netutils/netid_allocator.go diff --git a/pkg/util/netutils/netid_allocator.go b/pkg/util/netutils/netid_allocator.go deleted file mode 100644 index 55923450d71a..000000000000 --- a/pkg/util/netutils/netid_allocator.go +++ /dev/null @@ -1,54 +0,0 @@ -package netutils - -import ( - "fmt" -) - -type NetIDAllocator struct { - min uint32 - max uint32 - allocMap map[uint32]bool -} - -func NewNetIDAllocator(min uint32, max uint32, inUse []uint32) (*NetIDAllocator, error) { - if max <= min { - return nil, fmt.Errorf("Min should be lesser than max value (Min: %d, Max: %d)", min, max) - } - - amap := make(map[uint32]bool) - for _, netid := range inUse { - if netid < min || netid > max { - return nil, fmt.Errorf("Provided net id doesn't belong to range: [%d, %d]", min, max) - } - amap[netid] = true - } - - return &NetIDAllocator{min: min, max: max, allocMap: amap}, nil -} - -func (nia *NetIDAllocator) GetNetID() (uint32, error) { - var i uint32 - for i = nia.min; i <= nia.max; i++ { - taken, found := nia.allocMap[i] - if !found || !taken { - nia.allocMap[i] = true - return i, nil - } - } - - return 0, fmt.Errorf("No NetIDs available.") -} - -func (nia *NetIDAllocator) ReleaseNetID(netid uint32) error { - if nia.min > netid || nia.max < netid { - return fmt.Errorf("Provided net id %d doesn't belong to the given range [%d, %d]", netid, nia.min, nia.max) - } - - taken, found := nia.allocMap[netid] - if !found || !taken { - return fmt.Errorf("Provided net id %d is already available.", netid) - } - - nia.allocMap[netid] = false - return nil -} From 09c1521741fd7ca9f77d388b4d5452090fb5f4ef Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Tue, 9 Aug 2016 14:16:06 -0700 Subject: [PATCH 09/13] Make pod-network cli command to use ChangePodNetworkAnnotation instead of updating VNID directly This will ensure VNID is synchronized across add/delete/update operations. --- pkg/cmd/admin/network/join_projects.go | 12 ++-- pkg/cmd/admin/network/make_projects_global.go | 8 +-- pkg/cmd/admin/network/project_options.go | 65 +++++++++---------- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/pkg/cmd/admin/network/join_projects.go b/pkg/cmd/admin/network/join_projects.go index 2307b8dc0f67..ec5a24e892a1 100644 --- a/pkg/cmd/admin/network/join_projects.go +++ b/pkg/cmd/admin/network/join_projects.go @@ -11,6 +11,7 @@ import ( kerrors "k8s.io/kubernetes/pkg/util/errors" "github.com/openshift/origin/pkg/cmd/util/clientcmd" + sdnapi "github.com/openshift/origin/pkg/sdn/api" ) const ( @@ -79,10 +80,6 @@ func (j *JoinOptions) Validate() error { } func (j *JoinOptions) Run() error { - netID, err := j.Options.GetNetID(j.joinProjectName) - if err != nil { - return err - } projects, err := j.Options.GetProjects() if err != nil { return err @@ -90,9 +87,10 @@ func (j *JoinOptions) Run() error { errList := []error{} for _, project := range projects { - err = j.Options.CreateOrUpdateNetNamespace(project.ObjectMeta.Name, netID) - if err != nil { - errList = append(errList, fmt.Errorf("Project '%s' failed to join '%s', error: %v", project.ObjectMeta.Name, j.joinProjectName, err)) + if project.Name != j.joinProjectName { + if err = j.Options.UpdatePodNetwork(project.Name, sdnapi.JoinPodNetwork, j.joinProjectName); err != nil { + errList = append(errList, fmt.Errorf("Project %q failed to join %q, error: %v", project.Name, j.joinProjectName, err)) + } } } return kerrors.NewAggregate(errList) diff --git a/pkg/cmd/admin/network/make_projects_global.go b/pkg/cmd/admin/network/make_projects_global.go index 15fe58fa1fdf..64ddb2189e94 100644 --- a/pkg/cmd/admin/network/make_projects_global.go +++ b/pkg/cmd/admin/network/make_projects_global.go @@ -10,11 +10,10 @@ import ( kerrors "k8s.io/kubernetes/pkg/util/errors" "github.com/openshift/origin/pkg/cmd/util/clientcmd" + sdnapi "github.com/openshift/origin/pkg/sdn/api" ) const ( - globalVNID = uint32(0) - MakeGlobalProjectsNetworkCommandName = "make-projects-global" makeGlobalProjectsNetworkLong = ` @@ -71,9 +70,8 @@ func (m *MakeGlobalOptions) Run() error { errList := []error{} for _, project := range projects { - err = m.Options.CreateOrUpdateNetNamespace(project.ObjectMeta.Name, globalVNID) - if err != nil { - errList = append(errList, fmt.Errorf("Removing network isolation for project '%s' failed, error: %v", project.ObjectMeta.Name, err)) + if err = m.Options.UpdatePodNetwork(project.Name, sdnapi.GlobalPodNetwork, ""); err != nil { + errList = append(errList, fmt.Errorf("Removing network isolation for project %q failed, error: %v", project.Name, err)) } } return kerrors.NewAggregate(errList) diff --git a/pkg/cmd/admin/network/project_options.go b/pkg/cmd/admin/network/project_options.go index 07703f7778a6..1687434037a6 100644 --- a/pkg/cmd/admin/network/project_options.go +++ b/pkg/cmd/admin/network/project_options.go @@ -6,12 +6,12 @@ import ( "io" "reflect" "strings" + "time" "github.com/spf13/cobra" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" kclient "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/labels" @@ -144,48 +144,43 @@ func (p *ProjectOptions) GetProjects() ([]*api.Project, error) { return projectList, nil } -func (p *ProjectOptions) GetNetNamespaces() (*sdnapi.NetNamespaceList, error) { - netNamespaces, err := p.Oclient.NetNamespaces().List(kapi.ListOptions{}) - if err != nil { - return nil, err - } - return netNamespaces, nil -} +func (p *ProjectOptions) validateNetNamespace(netns *sdnapi.NetNamespace) error { + // Timeout: 10 secs + retries := 20 + retryInterval := 500 * time.Millisecond -func (p *ProjectOptions) GetNetID(name string) (uint32, error) { - var netID uint32 - netNamespaces, err := p.GetNetNamespaces() - if err != nil { - return netID, err - } + for i := 0; i < retries; i++ { + updatedNetNs, err := p.Oclient.NetNamespaces().Get(netns.NetName) + if err != nil { + return err + } - for _, netNs := range netNamespaces.Items { - if name == netNs.ObjectMeta.Name { - return netNs.NetID, nil + switch _, _, err := sdnapi.GetChangePodNetworkAnnotation(updatedNetNs); err { + case sdnapi.ErrorPodNetworkAnnotationNotFound: + return nil + default: + time.Sleep(retryInterval) } } - return netID, fmt.Errorf("Net ID not found for project: %s", name) + return fmt.Errorf("failed to apply pod network change for project %q", netns.NetName) } -func (p *ProjectOptions) CreateOrUpdateNetNamespace(name string, id uint32) error { - netns, err := p.Oclient.NetNamespaces().Get(name) +func (p *ProjectOptions) UpdatePodNetwork(nsName string, action sdnapi.PodNetworkAction, args string) error { + // Get corresponding NetNamespace for given namespace + netns, err := p.Oclient.NetNamespaces().Get(nsName) if err != nil { - // Create netns - netns := newNetNamespace(name, id) - _, err = p.Oclient.NetNamespaces().Create(netns) - } else if netns.NetID != id { - // Update netns - netns.NetID = id - _, err = p.Oclient.NetNamespaces().Update(netns) + return err } - return err -} -func newNetNamespace(name string, id uint32) *sdnapi.NetNamespace { - return &sdnapi.NetNamespace{ - TypeMeta: unversioned.TypeMeta{Kind: "NetNamespace"}, - ObjectMeta: kapi.ObjectMeta{Name: name}, - NetName: name, - NetID: id, + // Apply pod network change intent + sdnapi.SetChangePodNetworkAnnotation(netns, action, args) + + // Update NetNamespace object + _, err = p.Oclient.NetNamespaces().Update(netns) + if err != nil { + return err } + + // Validate SDN controller applied or rejected the intent + return p.validateNetNamespace(netns) } From e54838c7b083ac4dc9108c0ebff0e088c11461db Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Tue, 9 Aug 2016 14:29:37 -0700 Subject: [PATCH 10/13] CLI changes to support project network isolation --- pkg/cmd/admin/network/isolate_projects.go | 7 ++++--- pkg/cmd/admin/network/pod_network.go | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/admin/network/isolate_projects.go b/pkg/cmd/admin/network/isolate_projects.go index cd99a33bfff8..922db00afc5d 100644 --- a/pkg/cmd/admin/network/isolate_projects.go +++ b/pkg/cmd/admin/network/isolate_projects.go @@ -10,6 +10,7 @@ import ( kerrors "k8s.io/kubernetes/pkg/util/errors" "github.com/openshift/origin/pkg/cmd/util/clientcmd" + sdnapi "github.com/openshift/origin/pkg/sdn/api" ) const ( @@ -69,9 +70,9 @@ func (i *IsolateOptions) Run() error { errList := []error{} for _, project := range projects { - // TBD: Create or Update network namespace - // TODO: Fix this once we move VNID allocation to REST layer - errList = append(errList, fmt.Errorf("Project '%s' can not be isolated. Isolate project network feature yet to be implemented!", project.ObjectMeta.Name)) + if err = i.Options.UpdatePodNetwork(project.Name, sdnapi.IsolatePodNetwork, ""); err != nil { + errList = append(errList, fmt.Errorf("Network isolation for project %q failed, error: %v", project.Name, err)) + } } return kerrors.NewAggregate(errList) } diff --git a/pkg/cmd/admin/network/pod_network.go b/pkg/cmd/admin/network/pod_network.go index 285884993692..4d8064b90763 100644 --- a/pkg/cmd/admin/network/pod_network.go +++ b/pkg/cmd/admin/network/pod_network.go @@ -30,8 +30,7 @@ func NewCmdPodNetwork(name, fullName string, f *clientcmd.Factory, out io.Writer cmds.AddCommand(NewCmdJoinProjectsNetwork(JoinProjectsNetworkCommandName, fullName+" "+JoinProjectsNetworkCommandName, f, out)) cmds.AddCommand(NewCmdMakeGlobalProjectsNetwork(MakeGlobalProjectsNetworkCommandName, fullName+" "+MakeGlobalProjectsNetworkCommandName, f, out)) - // TODO: Enable isolate-projects subcommand once we move VNID allocation to REST layer - //cmds.AddCommand(NewCmdIsolateProjectsNetwork(IsolateProjectsNetworkCommandName, fullName+" "+IsolateProjectsNetworkCommandName, f, out)) + cmds.AddCommand(NewCmdIsolateProjectsNetwork(IsolateProjectsNetworkCommandName, fullName+" "+IsolateProjectsNetworkCommandName, f, out)) return cmds } From 718eab9c9d29d5d3affb715e0310a04755c97687 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Wed, 10 Aug 2016 12:46:36 -0700 Subject: [PATCH 11/13] Added test cases for 'oadm pod-network isolate-projects' --- test/extended/networking/pod_network_cli.go | 67 +++++++++++++++------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/test/extended/networking/pod_network_cli.go b/test/extended/networking/pod_network_cli.go index d77eef26cb8d..623153a89a75 100644 --- a/test/extended/networking/pod_network_cli.go +++ b/test/extended/networking/pod_network_cli.go @@ -19,38 +19,55 @@ var _ = Describe("[networking] pod-network admin commands", func() { f2 := e2e.NewDefaultFramework("net-isolation2") f3 := e2e.NewDefaultFramework("net-isolation3") - verifyJoinProjects := func(f1, f2, f3 *e2e.Framework, n NodeType) { - // Join project networks for f1 and f2 - Expect(joinProjects(oc, f1, f2)).To(Succeed()) - - // Check pod and service communication from f1 --> f2 and f2 --> f1 + // Pod and service communication from f1 --> f2 and f2 --> f1 should succeed + commSuccess := func(f1, f2 *e2e.Framework, n NodeType) { Expect(checkPodIsolation(f1, f2, n)).To(Succeed()) Expect(checkPodIsolation(f2, f1, n)).To(Succeed()) Expect(checkServiceConnectivity(f1, f2, n)).To(Succeed()) Expect(checkServiceConnectivity(f2, f1, n)).To(Succeed()) + } + // Pod and service communication from f1 --> f2 and f2 --> f1 should fail + commFailure := func(f1, f2 *e2e.Framework, n NodeType) { + Expect(checkPodIsolation(f1, f2, n)).NotTo(Succeed()) + Expect(checkPodIsolation(f2, f1, n)).NotTo(Succeed()) + Expect(checkServiceConnectivity(f1, f2, n)).NotTo(Succeed()) + Expect(checkServiceConnectivity(f2, f1, n)).NotTo(Succeed()) + } + + verifyJoinProjects := func(f1, f2, f3 *e2e.Framework, n NodeType) { + // Join project networks for f1 and f2 + Expect(joinProjects(oc, f1, f2)).To(Succeed()) - // Check pod and service communication from f1 --> f3 and f3 --> f1 - Expect(checkPodIsolation(f1, f3, n)).NotTo(Succeed()) - Expect(checkPodIsolation(f3, f1, n)).NotTo(Succeed()) - Expect(checkServiceConnectivity(f1, f3, n)).NotTo(Succeed()) - Expect(checkServiceConnectivity(f3, f1, n)).NotTo(Succeed()) + commSuccess(f1, f2, n) + commFailure(f1, f3, n) } verifyMakeProjectsGlobal := func(f1, f2, f3 *e2e.Framework, n NodeType) { // Make project network for f1 global Expect(makeProjectsGlobal(oc, f1)).To(Succeed()) - // Check pod and service communication from f1 --> f2 and f2 --> f1 - Expect(checkPodIsolation(f1, f2, n)).To(Succeed()) - Expect(checkPodIsolation(f2, f1, n)).To(Succeed()) - Expect(checkServiceConnectivity(f1, f2, n)).To(Succeed()) - Expect(checkServiceConnectivity(f2, f1, n)).To(Succeed()) + commSuccess(f1, f2, n) + commSuccess(f1, f3, n) + } + + verifyIsolateProjects := func(f1, f2, f3 *e2e.Framework, n NodeType) { + // Join project networks for f1 and f2 + Expect(joinProjects(oc, f1, f2)).To(Succeed()) + + // Isolate project network for f1 + Expect(isolateProjects(oc, f1)).To(Succeed()) + + commFailure(f1, f2, n) + commFailure(f1, f3, n) + + // Make project network for f1 global + Expect(makeProjectsGlobal(oc, f1)).To(Succeed()) - // Check pod and service communication from f1 --> f3 and f3 --> f1 - Expect(checkPodIsolation(f1, f3, n)).To(Succeed()) - Expect(checkPodIsolation(f3, f1, n)).To(Succeed()) - Expect(checkServiceConnectivity(f1, f3, n)).To(Succeed()) - Expect(checkServiceConnectivity(f3, f1, n)).To(Succeed()) + // Isolate project network for f1 + Expect(isolateProjects(oc, f1)).To(Succeed()) + + commFailure(f1, f2, n) + commFailure(f1, f3, n) } It("join-projects should allow communication between pods/services in different projects on the same node", func() { @@ -65,6 +82,12 @@ var _ = Describe("[networking] pod-network admin commands", func() { It("make-projects-global should allow project to communicate with any pod in the cluster on different nodes", func() { verifyMakeProjectsGlobal(f1, f2, f3, DIFFERENT_NODE) }) + It("isolate-projects should not allow project to communicate with other projects in the cluster on the same node", func() { + verifyIsolateProjects(f1, f2, f3, SAME_NODE) + }) + It("isolate-projects should not allow project to communicate with other projects in the cluster on different nodes", func() { + verifyIsolateProjects(f1, f2, f3, DIFFERENT_NODE) + }) }) }) @@ -75,3 +98,7 @@ func joinProjects(oc *exutil.CLI, f1, f2 *e2e.Framework) error { func makeProjectsGlobal(oc *exutil.CLI, f *e2e.Framework) error { return oc.Run("adm").Args("pod-network", "make-projects-global", f.Namespace.Name).Execute() } + +func isolateProjects(oc *exutil.CLI, f *e2e.Framework) error { + return oc.Run("adm").Args("pod-network", "isolate-projects", f.Namespace.Name).Execute() +} From 053eb168fd314a759f593e181bf7492db2bafcd3 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Mon, 15 Aug 2016 15:33:50 -0700 Subject: [PATCH 12/13] Updated auto generated bash completions for pod-network CLI commands --- contrib/completions/bash/oadm | 47 +++++++++++++++ contrib/completions/bash/oc | 46 +++++++++++++++ contrib/completions/bash/openshift | 94 ++++++++++++++++++++++++++++++ contrib/completions/zsh/oadm | 47 +++++++++++++++ contrib/completions/zsh/oc | 46 +++++++++++++++ contrib/completions/zsh/openshift | 94 ++++++++++++++++++++++++++++++ 6 files changed, 374 insertions(+) diff --git a/contrib/completions/bash/oadm b/contrib/completions/bash/oadm index 57e1a44f215c..89c1821b8a5a 100644 --- a/contrib/completions/bash/oadm +++ b/contrib/completions/bash/oadm @@ -2598,6 +2598,52 @@ _oadm_overwrite-policy() noun_aliases=() } +_oadm_pod-network_isolate-projects() +{ + last_command="oadm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oadm_pod-network_join-projects() { last_command="oadm_pod-network_join-projects" @@ -2696,6 +2742,7 @@ _oadm_pod-network() { last_command="oadm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") diff --git a/contrib/completions/bash/oc b/contrib/completions/bash/oc index ef23a15e9475..417937791380 100644 --- a/contrib/completions/bash/oc +++ b/contrib/completions/bash/oc @@ -2681,6 +2681,51 @@ _oc_adm_overwrite-policy() noun_aliases=() } +_oc_adm_pod-network_isolate-projects() +{ + last_command="oc_adm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oc_adm_pod-network_join-projects() { last_command="oc_adm_pod-network_join-projects" @@ -2777,6 +2822,7 @@ _oc_adm_pod-network() { last_command="oc_adm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") diff --git a/contrib/completions/bash/openshift b/contrib/completions/bash/openshift index f4dca39295d9..632f126b4ca2 100644 --- a/contrib/completions/bash/openshift +++ b/contrib/completions/bash/openshift @@ -2598,6 +2598,52 @@ _openshift_admin_overwrite-policy() noun_aliases=() } +_openshift_admin_pod-network_isolate-projects() +{ + last_command="openshift_admin_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _openshift_admin_pod-network_join-projects() { last_command="openshift_admin_pod-network_join-projects" @@ -2696,6 +2742,7 @@ _openshift_admin_pod-network() { last_command="openshift_admin_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") @@ -6919,6 +6966,52 @@ _openshift_cli_adm_overwrite-policy() noun_aliases=() } +_openshift_cli_adm_pod-network_isolate-projects() +{ + last_command="openshift_cli_adm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _openshift_cli_adm_pod-network_join-projects() { last_command="openshift_cli_adm_pod-network_join-projects" @@ -7017,6 +7110,7 @@ _openshift_cli_adm_pod-network() { last_command="openshift_cli_adm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") diff --git a/contrib/completions/zsh/oadm b/contrib/completions/zsh/oadm index b7a3ebcd7202..a61497b0d55b 100644 --- a/contrib/completions/zsh/oadm +++ b/contrib/completions/zsh/oadm @@ -2759,6 +2759,52 @@ _oadm_overwrite-policy() noun_aliases=() } +_oadm_pod-network_isolate-projects() +{ + last_command="oadm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oadm_pod-network_join-projects() { last_command="oadm_pod-network_join-projects" @@ -2857,6 +2903,7 @@ _oadm_pod-network() { last_command="oadm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") diff --git a/contrib/completions/zsh/oc b/contrib/completions/zsh/oc index 4ce883b191c7..7814f2e42d1b 100644 --- a/contrib/completions/zsh/oc +++ b/contrib/completions/zsh/oc @@ -2842,6 +2842,51 @@ _oc_adm_overwrite-policy() noun_aliases=() } +_oc_adm_pod-network_isolate-projects() +{ + last_command="oc_adm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oc_adm_pod-network_join-projects() { last_command="oc_adm_pod-network_join-projects" @@ -2938,6 +2983,7 @@ _oc_adm_pod-network() { last_command="oc_adm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") diff --git a/contrib/completions/zsh/openshift b/contrib/completions/zsh/openshift index 628e47c532d4..0164d4b0b228 100644 --- a/contrib/completions/zsh/openshift +++ b/contrib/completions/zsh/openshift @@ -2759,6 +2759,52 @@ _openshift_admin_overwrite-policy() noun_aliases=() } +_openshift_admin_pod-network_isolate-projects() +{ + last_command="openshift_admin_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _openshift_admin_pod-network_join-projects() { last_command="openshift_admin_pod-network_join-projects" @@ -2857,6 +2903,7 @@ _openshift_admin_pod-network() { last_command="openshift_admin_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") @@ -7080,6 +7127,52 @@ _openshift_cli_adm_overwrite-policy() noun_aliases=() } +_openshift_cli_adm_pod-network_isolate-projects() +{ + last_command="openshift_cli_adm_pod-network_isolate-projects" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--selector=") + local_nonpersistent_flags+=("--selector=") + flags+=("--api-version=") + flags+=("--as=") + flags+=("--certificate-authority=") + flags_with_completion+=("--certificate-authority") + flags_completion+=("_filedir") + flags+=("--client-certificate=") + flags_with_completion+=("--client-certificate") + flags_completion+=("_filedir") + flags+=("--client-key=") + flags_with_completion+=("--client-key") + flags_completion+=("_filedir") + flags+=("--cluster=") + flags+=("--config=") + flags_with_completion+=("--config") + flags_completion+=("_filedir") + flags+=("--context=") + flags+=("--google-json-key=") + flags+=("--insecure-skip-tls-verify") + flags+=("--log-flush-frequency=") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + two_word_flags+=("-n") + flags+=("--server=") + flags+=("--token=") + flags+=("--user=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _openshift_cli_adm_pod-network_join-projects() { last_command="openshift_cli_adm_pod-network_join-projects" @@ -7178,6 +7271,7 @@ _openshift_cli_adm_pod-network() { last_command="openshift_cli_adm_pod-network" commands=() + commands+=("isolate-projects") commands+=("join-projects") commands+=("make-projects-global") From 047c65da8be914f29a583fdeafbb99b15b9d2e57 Mon Sep 17 00:00:00 2001 From: Ravi Sankar Penta Date: Fri, 12 Aug 2016 13:52:06 -0700 Subject: [PATCH 13/13] Updated auto generated doc for pod-network CLI commands --- docs/generated/oadm_by_example_content.adoc | 16 +++ docs/generated/oc_by_example_content.adoc | 16 +++ docs/man/man1/.files_generated_oadm | 1 + docs/man/man1/.files_generated_oc | 1 + docs/man/man1/.files_generated_openshift | 2 + .../man1/oadm-pod-network-isolate-projects.1 | 116 ++++++++++++++++++ docs/man/man1/oadm-pod-network.1 | 2 +- .../oc-adm-pod-network-isolate-projects.1 | 116 ++++++++++++++++++ docs/man/man1/oc-adm-pod-network.1 | 2 +- ...shift-admin-pod-network-isolate-projects.1 | 116 ++++++++++++++++++ docs/man/man1/openshift-admin-pod-network.1 | 2 +- ...ift-cli-adm-pod-network-isolate-projects.1 | 116 ++++++++++++++++++ docs/man/man1/openshift-cli-adm-pod-network.1 | 2 +- 13 files changed, 504 insertions(+), 4 deletions(-) create mode 100644 docs/man/man1/oadm-pod-network-isolate-projects.1 create mode 100644 docs/man/man1/oc-adm-pod-network-isolate-projects.1 create mode 100644 docs/man/man1/openshift-admin-pod-network-isolate-projects.1 create mode 100644 docs/man/man1/openshift-cli-adm-pod-network-isolate-projects.1 diff --git a/docs/generated/oadm_by_example_content.adoc b/docs/generated/oadm_by_example_content.adoc index 20d9608b9eac..f9f8dcf2e6a8 100644 --- a/docs/generated/oadm_by_example_content.adoc +++ b/docs/generated/oadm_by_example_content.adoc @@ -409,6 +409,22 @@ Update the stored version of API objects ==== +== oadm pod-network isolate-projects +Isolate project network + +==== + +[options="nowrap"] +---- + # Provide isolation for project p1 + oadm pod-network isolate-projects + + # Allow all projects with label name=top-secret to have their own isolated project network + oadm pod-network isolate-projects --selector='name=top-secret' +---- +==== + + == oadm pod-network join-projects Join project network diff --git a/docs/generated/oc_by_example_content.adoc b/docs/generated/oc_by_example_content.adoc index af374ac341c7..12652ed49781 100644 --- a/docs/generated/oc_by_example_content.adoc +++ b/docs/generated/oc_by_example_content.adoc @@ -409,6 +409,22 @@ Update the stored version of API objects ==== +== oc adm pod-network isolate-projects +Isolate project network + +==== + +[options="nowrap"] +---- + # Provide isolation for project p1 + oc adm pod-network isolate-projects + + # Allow all projects with label name=top-secret to have their own isolated project network + oc adm pod-network isolate-projects --selector='name=top-secret' +---- +==== + + == oc adm pod-network join-projects Join project network diff --git a/docs/man/man1/.files_generated_oadm b/docs/man/man1/.files_generated_oadm index 7bd84e7f32c4..c54dadbec01b 100644 --- a/docs/man/man1/.files_generated_oadm +++ b/docs/man/man1/.files_generated_oadm @@ -45,6 +45,7 @@ oadm-migrate.1 oadm-new-project.1 oadm-options.1 oadm-overwrite-policy.1 +oadm-pod-network-isolate-projects.1 oadm-pod-network-join-projects.1 oadm-pod-network-make-projects-global.1 oadm-pod-network.1 diff --git a/docs/man/man1/.files_generated_oc b/docs/man/man1/.files_generated_oc index a8764b64d0f6..9221546dc5c9 100644 --- a/docs/man/man1/.files_generated_oc +++ b/docs/man/man1/.files_generated_oc @@ -45,6 +45,7 @@ oc-adm-migrate.1 oc-adm-new-project.1 oc-adm-options.1 oc-adm-overwrite-policy.1 +oc-adm-pod-network-isolate-projects.1 oc-adm-pod-network-join-projects.1 oc-adm-pod-network-make-projects-global.1 oc-adm-pod-network.1 diff --git a/docs/man/man1/.files_generated_openshift b/docs/man/man1/.files_generated_openshift index b2ed430bed06..be3db7575be9 100644 --- a/docs/man/man1/.files_generated_openshift +++ b/docs/man/man1/.files_generated_openshift @@ -45,6 +45,7 @@ openshift-admin-migrate.1 openshift-admin-new-project.1 openshift-admin-options.1 openshift-admin-overwrite-policy.1 +openshift-admin-pod-network-isolate-projects.1 openshift-admin-pod-network-join-projects.1 openshift-admin-pod-network-make-projects-global.1 openshift-admin-pod-network.1 @@ -127,6 +128,7 @@ openshift-cli-adm-migrate.1 openshift-cli-adm-new-project.1 openshift-cli-adm-options.1 openshift-cli-adm-overwrite-policy.1 +openshift-cli-adm-pod-network-isolate-projects.1 openshift-cli-adm-pod-network-join-projects.1 openshift-cli-adm-pod-network-make-projects-global.1 openshift-cli-adm-pod-network.1 diff --git a/docs/man/man1/oadm-pod-network-isolate-projects.1 b/docs/man/man1/oadm-pod-network-isolate-projects.1 new file mode 100644 index 000000000000..2660917bd901 --- /dev/null +++ b/docs/man/man1/oadm-pod-network-isolate-projects.1 @@ -0,0 +1,116 @@ +.TH "OADM POD-NETWORK" "1" " Openshift CLI User Manuals" "Openshift" "June 2016" "" + + +.SH NAME +.PP +oadm pod\-network isolate\-projects \- Isolate project network + + +.SH SYNOPSIS +.PP +\fBoadm pod\-network isolate\-projects\fP [OPTIONS] + + +.SH DESCRIPTION +.PP +Isolate project network + +.PP +Allows projects to isolate their network from other projects when using the redhat/openshift\-ovs\-multitenant network plugin. + + +.SH OPTIONS +.PP +\fB\-\-selector\fP="" + Label selector to filter projects. Either pass one/more projects as arguments or use this project selector + + +.SH OPTIONS INHERITED FROM PARENT COMMANDS +.PP +\fB\-\-api\-version\fP="" + DEPRECATED: The API version to use when talking to the server + +.PP +\fB\-\-as\fP="" + Username to impersonate for the operation. + +.PP +\fB\-\-certificate\-authority\fP="" + Path to a cert. file for the certificate authority. + +.PP +\fB\-\-client\-certificate\fP="" + Path to a client certificate file for TLS. + +.PP +\fB\-\-client\-key\fP="" + Path to a client key file for TLS. + +.PP +\fB\-\-cluster\fP="" + The name of the kubeconfig cluster to use + +.PP +\fB\-\-config\fP="" + Path to the config file to use for CLI requests. + +.PP +\fB\-\-context\fP="" + The name of the kubeconfig context to use + +.PP +\fB\-\-google\-json\-key\fP="" + The Google Cloud Platform Service Account JSON Key to use for authentication. + +.PP +\fB\-\-insecure\-skip\-tls\-verify\fP=false + If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. + +.PP +\fB\-\-log\-flush\-frequency\fP=0 + Maximum number of seconds between log flushes + +.PP +\fB\-\-match\-server\-version\fP=false + Require server version to match client version + +.PP +\fB\-n\fP, \fB\-\-namespace\fP="" + If present, the namespace scope for this CLI request. + +.PP +\fB\-\-server\fP="" + The address and port of the Kubernetes API server + +.PP +\fB\-\-token\fP="" + Bearer token for authentication to the API server. + +.PP +\fB\-\-user\fP="" + The name of the kubeconfig user to use + + +.SH EXAMPLE +.PP +.RS + +.nf + # Provide isolation for project p1 + oadm pod\-network isolate\-projects + + # Allow all projects with label name=top\-secret to have their own isolated project network + oadm pod\-network isolate\-projects \-\-selector='name=top\-secret' + +.fi +.RE + + +.SH SEE ALSO +.PP +\fBoadm\-pod\-network(1)\fP, + + +.SH HISTORY +.PP +June 2016, Ported from the Kubernetes man\-doc generator diff --git a/docs/man/man1/oadm-pod-network.1 b/docs/man/man1/oadm-pod-network.1 index 4d5bbbf4a64b..dee154dc6236 100644 --- a/docs/man/man1/oadm-pod-network.1 +++ b/docs/man/man1/oadm-pod-network.1 @@ -87,7 +87,7 @@ This command provides common pod network operations for administrators. .SH SEE ALSO .PP -\fBoadm(1)\fP, \fBoadm\-pod\-network\-join\-projects(1)\fP, \fBoadm\-pod\-network\-make\-projects\-global(1)\fP, +\fBoadm(1)\fP, \fBoadm\-pod\-network\-isolate\-projects(1)\fP, \fBoadm\-pod\-network\-join\-projects(1)\fP, \fBoadm\-pod\-network\-make\-projects\-global(1)\fP, .SH HISTORY diff --git a/docs/man/man1/oc-adm-pod-network-isolate-projects.1 b/docs/man/man1/oc-adm-pod-network-isolate-projects.1 new file mode 100644 index 000000000000..15e0d7455c6e --- /dev/null +++ b/docs/man/man1/oc-adm-pod-network-isolate-projects.1 @@ -0,0 +1,116 @@ +.TH "OC ADM POD-NETWORK" "1" " Openshift CLI User Manuals" "Openshift" "June 2016" "" + + +.SH NAME +.PP +oc adm pod\-network isolate\-projects \- Isolate project network + + +.SH SYNOPSIS +.PP +\fBoc adm pod\-network isolate\-projects\fP [OPTIONS] + + +.SH DESCRIPTION +.PP +Isolate project network + +.PP +Allows projects to isolate their network from other projects when using the redhat/openshift\-ovs\-multitenant network plugin. + + +.SH OPTIONS +.PP +\fB\-\-selector\fP="" + Label selector to filter projects. Either pass one/more projects as arguments or use this project selector + + +.SH OPTIONS INHERITED FROM PARENT COMMANDS +.PP +\fB\-\-api\-version\fP="" + DEPRECATED: The API version to use when talking to the server + +.PP +\fB\-\-as\fP="" + Username to impersonate for the operation. + +.PP +\fB\-\-certificate\-authority\fP="" + Path to a cert. file for the certificate authority. + +.PP +\fB\-\-client\-certificate\fP="" + Path to a client certificate file for TLS. + +.PP +\fB\-\-client\-key\fP="" + Path to a client key file for TLS. + +.PP +\fB\-\-cluster\fP="" + The name of the kubeconfig cluster to use + +.PP +\fB\-\-config\fP="" + Path to the config file to use for CLI requests. + +.PP +\fB\-\-context\fP="" + The name of the kubeconfig context to use + +.PP +\fB\-\-google\-json\-key\fP="" + The Google Cloud Platform Service Account JSON Key to use for authentication. + +.PP +\fB\-\-insecure\-skip\-tls\-verify\fP=false + If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. + +.PP +\fB\-\-log\-flush\-frequency\fP=0 + Maximum number of seconds between log flushes + +.PP +\fB\-\-match\-server\-version\fP=false + Require server version to match client version + +.PP +\fB\-n\fP, \fB\-\-namespace\fP="" + If present, the namespace scope for this CLI request. + +.PP +\fB\-\-server\fP="" + The address and port of the Kubernetes API server + +.PP +\fB\-\-token\fP="" + Bearer token for authentication to the API server. + +.PP +\fB\-\-user\fP="" + The name of the kubeconfig user to use + + +.SH EXAMPLE +.PP +.RS + +.nf + # Provide isolation for project p1 + oc adm pod\-network isolate\-projects + + # Allow all projects with label name=top\-secret to have their own isolated project network + oc adm pod\-network isolate\-projects \-\-selector='name=top\-secret' + +.fi +.RE + + +.SH SEE ALSO +.PP +\fBoc\-adm\-pod\-network(1)\fP, + + +.SH HISTORY +.PP +June 2016, Ported from the Kubernetes man\-doc generator diff --git a/docs/man/man1/oc-adm-pod-network.1 b/docs/man/man1/oc-adm-pod-network.1 index 55e312d7e916..3205838c83bd 100644 --- a/docs/man/man1/oc-adm-pod-network.1 +++ b/docs/man/man1/oc-adm-pod-network.1 @@ -87,7 +87,7 @@ This command provides common pod network operations for administrators. .SH SEE ALSO .PP -\fBoc\-adm(1)\fP, \fBoc\-adm\-pod\-network\-join\-projects(1)\fP, \fBoc\-adm\-pod\-network\-make\-projects\-global(1)\fP, +\fBoc\-adm(1)\fP, \fBoc\-adm\-pod\-network\-isolate\-projects(1)\fP, \fBoc\-adm\-pod\-network\-join\-projects(1)\fP, \fBoc\-adm\-pod\-network\-make\-projects\-global(1)\fP, .SH HISTORY diff --git a/docs/man/man1/openshift-admin-pod-network-isolate-projects.1 b/docs/man/man1/openshift-admin-pod-network-isolate-projects.1 new file mode 100644 index 000000000000..c69e7e4397a3 --- /dev/null +++ b/docs/man/man1/openshift-admin-pod-network-isolate-projects.1 @@ -0,0 +1,116 @@ +.TH "OPENSHIFT ADMIN POD-NETWORK" "1" " Openshift CLI User Manuals" "Openshift" "June 2016" "" + + +.SH NAME +.PP +openshift admin pod\-network isolate\-projects \- Isolate project network + + +.SH SYNOPSIS +.PP +\fBopenshift admin pod\-network isolate\-projects\fP [OPTIONS] + + +.SH DESCRIPTION +.PP +Isolate project network + +.PP +Allows projects to isolate their network from other projects when using the redhat/openshift\-ovs\-multitenant network plugin. + + +.SH OPTIONS +.PP +\fB\-\-selector\fP="" + Label selector to filter projects. Either pass one/more projects as arguments or use this project selector + + +.SH OPTIONS INHERITED FROM PARENT COMMANDS +.PP +\fB\-\-api\-version\fP="" + DEPRECATED: The API version to use when talking to the server + +.PP +\fB\-\-as\fP="" + Username to impersonate for the operation. + +.PP +\fB\-\-certificate\-authority\fP="" + Path to a cert. file for the certificate authority. + +.PP +\fB\-\-client\-certificate\fP="" + Path to a client certificate file for TLS. + +.PP +\fB\-\-client\-key\fP="" + Path to a client key file for TLS. + +.PP +\fB\-\-cluster\fP="" + The name of the kubeconfig cluster to use + +.PP +\fB\-\-config\fP="" + Path to the config file to use for CLI requests. + +.PP +\fB\-\-context\fP="" + The name of the kubeconfig context to use + +.PP +\fB\-\-google\-json\-key\fP="" + The Google Cloud Platform Service Account JSON Key to use for authentication. + +.PP +\fB\-\-insecure\-skip\-tls\-verify\fP=false + If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. + +.PP +\fB\-\-log\-flush\-frequency\fP=0 + Maximum number of seconds between log flushes + +.PP +\fB\-\-match\-server\-version\fP=false + Require server version to match client version + +.PP +\fB\-n\fP, \fB\-\-namespace\fP="" + If present, the namespace scope for this CLI request. + +.PP +\fB\-\-server\fP="" + The address and port of the Kubernetes API server + +.PP +\fB\-\-token\fP="" + Bearer token for authentication to the API server. + +.PP +\fB\-\-user\fP="" + The name of the kubeconfig user to use + + +.SH EXAMPLE +.PP +.RS + +.nf + # Provide isolation for project p1 + openshift admin pod\-network isolate\-projects + + # Allow all projects with label name=top\-secret to have their own isolated project network + openshift admin pod\-network isolate\-projects \-\-selector='name=top\-secret' + +.fi +.RE + + +.SH SEE ALSO +.PP +\fBopenshift\-admin\-pod\-network(1)\fP, + + +.SH HISTORY +.PP +June 2016, Ported from the Kubernetes man\-doc generator diff --git a/docs/man/man1/openshift-admin-pod-network.1 b/docs/man/man1/openshift-admin-pod-network.1 index 40638183a42b..979e64397120 100644 --- a/docs/man/man1/openshift-admin-pod-network.1 +++ b/docs/man/man1/openshift-admin-pod-network.1 @@ -87,7 +87,7 @@ This command provides common pod network operations for administrators. .SH SEE ALSO .PP -\fBopenshift\-admin(1)\fP, \fBopenshift\-admin\-pod\-network\-join\-projects(1)\fP, \fBopenshift\-admin\-pod\-network\-make\-projects\-global(1)\fP, +\fBopenshift\-admin(1)\fP, \fBopenshift\-admin\-pod\-network\-isolate\-projects(1)\fP, \fBopenshift\-admin\-pod\-network\-join\-projects(1)\fP, \fBopenshift\-admin\-pod\-network\-make\-projects\-global(1)\fP, .SH HISTORY diff --git a/docs/man/man1/openshift-cli-adm-pod-network-isolate-projects.1 b/docs/man/man1/openshift-cli-adm-pod-network-isolate-projects.1 new file mode 100644 index 000000000000..6277c6f3fa8a --- /dev/null +++ b/docs/man/man1/openshift-cli-adm-pod-network-isolate-projects.1 @@ -0,0 +1,116 @@ +.TH "OPENSHIFT CLI ADM POD-NETWORK" "1" " Openshift CLI User Manuals" "Openshift" "June 2016" "" + + +.SH NAME +.PP +openshift cli adm pod\-network isolate\-projects \- Isolate project network + + +.SH SYNOPSIS +.PP +\fBopenshift cli adm pod\-network isolate\-projects\fP [OPTIONS] + + +.SH DESCRIPTION +.PP +Isolate project network + +.PP +Allows projects to isolate their network from other projects when using the redhat/openshift\-ovs\-multitenant network plugin. + + +.SH OPTIONS +.PP +\fB\-\-selector\fP="" + Label selector to filter projects. Either pass one/more projects as arguments or use this project selector + + +.SH OPTIONS INHERITED FROM PARENT COMMANDS +.PP +\fB\-\-api\-version\fP="" + DEPRECATED: The API version to use when talking to the server + +.PP +\fB\-\-as\fP="" + Username to impersonate for the operation. + +.PP +\fB\-\-certificate\-authority\fP="" + Path to a cert. file for the certificate authority. + +.PP +\fB\-\-client\-certificate\fP="" + Path to a client certificate file for TLS. + +.PP +\fB\-\-client\-key\fP="" + Path to a client key file for TLS. + +.PP +\fB\-\-cluster\fP="" + The name of the kubeconfig cluster to use + +.PP +\fB\-\-config\fP="" + Path to the config file to use for CLI requests. + +.PP +\fB\-\-context\fP="" + The name of the kubeconfig context to use + +.PP +\fB\-\-google\-json\-key\fP="" + The Google Cloud Platform Service Account JSON Key to use for authentication. + +.PP +\fB\-\-insecure\-skip\-tls\-verify\fP=false + If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. + +.PP +\fB\-\-log\-flush\-frequency\fP=0 + Maximum number of seconds between log flushes + +.PP +\fB\-\-match\-server\-version\fP=false + Require server version to match client version + +.PP +\fB\-n\fP, \fB\-\-namespace\fP="" + If present, the namespace scope for this CLI request. + +.PP +\fB\-\-server\fP="" + The address and port of the Kubernetes API server + +.PP +\fB\-\-token\fP="" + Bearer token for authentication to the API server. + +.PP +\fB\-\-user\fP="" + The name of the kubeconfig user to use + + +.SH EXAMPLE +.PP +.RS + +.nf + # Provide isolation for project p1 + openshift cli adm pod\-network isolate\-projects + + # Allow all projects with label name=top\-secret to have their own isolated project network + openshift cli adm pod\-network isolate\-projects \-\-selector='name=top\-secret' + +.fi +.RE + + +.SH SEE ALSO +.PP +\fBopenshift\-cli\-adm\-pod\-network(1)\fP, + + +.SH HISTORY +.PP +June 2016, Ported from the Kubernetes man\-doc generator diff --git a/docs/man/man1/openshift-cli-adm-pod-network.1 b/docs/man/man1/openshift-cli-adm-pod-network.1 index 1f1be0821f21..cfc333846c67 100644 --- a/docs/man/man1/openshift-cli-adm-pod-network.1 +++ b/docs/man/man1/openshift-cli-adm-pod-network.1 @@ -87,7 +87,7 @@ This command provides common pod network operations for administrators. .SH SEE ALSO .PP -\fBopenshift\-cli\-adm(1)\fP, \fBopenshift\-cli\-adm\-pod\-network\-join\-projects(1)\fP, \fBopenshift\-cli\-adm\-pod\-network\-make\-projects\-global(1)\fP, +\fBopenshift\-cli\-adm(1)\fP, \fBopenshift\-cli\-adm\-pod\-network\-isolate\-projects(1)\fP, \fBopenshift\-cli\-adm\-pod\-network\-join\-projects(1)\fP, \fBopenshift\-cli\-adm\-pod\-network\-make\-projects\-global(1)\fP, .SH HISTORY