From 1342794609c6257af9484ad594825d8d53f59624 Mon Sep 17 00:00:00 2001 From: Christophe de Carvalho Date: Thu, 30 Jul 2020 13:39:17 +0200 Subject: [PATCH 1/4] networkd: migrate network cached to new network resource type We replace the full network type with network resource when networkd tried to read cached network during container network configuration --- pkg/network.go | 18 +++++++++++----- pkg/network/networker.go | 43 +++++++++++++++++++++++++++++++++---- pkg/network/nr/container.go | 2 +- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/pkg/network.go b/pkg/network.go index bcb055ce6..d5de6573a 100644 --- a/pkg/network.go +++ b/pkg/network.go @@ -76,9 +76,16 @@ type Networker interface { PublicAddresses(ctx context.Context) <-chan NetlinkAddresses } -// // Network represent the description if a user private network -// type Network struct { -// } +// Network represent the description if a user private network +type Network struct { + Name string `json:"name"` + //unique id inside the reservation is an autoincrement (USE AS NET_ID) + NetID NetID `json:"net_id"` + // IP range of the network, must be an IPv4 /16 + IPRange types.IPNet `json:"ip_range"` + + NetResources []NetResource `json:"net_resources"` +} // NetResource is the description of a part of a network local to a specific node type NetResource struct { @@ -112,9 +119,10 @@ type Peer struct { // NetID is a type defining the ID of a network type NetID string +// Version of the network workloads keep in cache by networkd var ( - // NetworkSchemaV1 network object schema version 1.0.0 NetworkSchemaV1 = versioned.MustParse("1.0.0") + NetworkSchemaV2 = versioned.MustParse("2.0.0") // NetworkSchemaLatestVersion network object latest version - NetworkSchemaLatestVersion = NetworkSchemaV1 + NetworkSchemaLatestVersion = NetworkSchemaV2 ) diff --git a/pkg/network/networker.go b/pkg/network/networker.go index f9d2fc5dd..9f93caa98 100644 --- a/pkg/network/networker.go +++ b/pkg/network/networker.go @@ -533,11 +533,12 @@ func (n *networker) DeleteNR(netNR pkg.NetResource) error { func (n *networker) networkOf(id string) (nr pkg.NetResource, err error) { path := filepath.Join(n.networkDir, string(id)) - file, err := os.Open(path) + file, err := os.OpenFile(path, os.O_RDWR, 0660) if err != nil { return nr, err } defer file.Close() + reader, err := versioned.NewReader(file) if versioned.IsNotVersioned(err) { // old data that doesn't have any version information @@ -553,14 +554,48 @@ func (n *networker) networkOf(id string) (nr pkg.NetResource, err error) { var net pkg.NetResource dec := json.NewDecoder(reader) - validV1 := versioned.MustParseRange(fmt.Sprintf("<=%s", pkg.NetworkSchemaV1)) + version := reader.Version() + validV1 := versioned.MustParseRange(fmt.Sprintf("=%s", pkg.NetworkSchemaV1)) + validLatest := versioned.MustParseRange(fmt.Sprintf("<=%s", pkg.NetworkSchemaLatestVersion)) + + if validV1(version) { + // we found a v1 full network definition, let migrate it to v2 network resource + var network pkg.Network + if err := dec.Decode(&network); err != nil { + return nr, err + } + + for _, nr := range network.NetResources { + if nr.NodeID == n.identity.NodeID().Identity() { + net = nr + break + } + } + net.Name = network.Name + net.NetworkIPRange = network.IPRange + net.NetID = network.NetID + + // overwrite the old version network with latest version + // old data that doesn't have any version information + if _, err := file.Seek(0, 0); err != nil { + return nr, err + } + + writer, err := versioned.NewWriter(file, pkg.NetworkSchemaLatestVersion) + if err != nil { + return nr, err + } + + if err := json.NewEncoder(writer).Encode(&net); err != nil { + return nr, err + } - if validV1(reader.Version()) { + } else if validLatest(version) { if err := dec.Decode(&net); err != nil { return nr, err } } else { - return nr, fmt.Errorf("unknown network object version (%s)", reader.Version()) + return nr, fmt.Errorf("unknown network object version (%s)", version) } return net, nil diff --git a/pkg/network/nr/container.go b/pkg/network/nr/container.go index 387658779..55f4655bd 100644 --- a/pkg/network/nr/container.go +++ b/pkg/network/nr/container.go @@ -100,7 +100,7 @@ func (nr *NetResource) Join(containerID string, addrs []net.IP, publicIP6 bool) ipnet.IP[len(ipnet.IP)-1] = 0x01 routes := []*netlink.Route{ - &netlink.Route{ + { Dst: &net.IPNet{ IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(0, 32), From efc8676626ffadd9e76c812cd89476c1a868145d Mon Sep 17 00:00:00 2001 From: Christophe de Carvalho Date: Thu, 30 Jul 2020 13:40:24 +0200 Subject: [PATCH 2/4] skip network migration verification I left a TODO here. Or we just skip this and we need to implement a proper comparaison between old and new network workload type --- pkg/provision/engine.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/provision/engine.go b/pkg/provision/engine.go index 3cd9d1280..2fdc40638 100644 --- a/pkg/provision/engine.go +++ b/pkg/provision/engine.go @@ -342,9 +342,13 @@ func (e *Engine) migrateToPool(ctx context.Context, r *Reservation) error { log.Info().Str("reference", r.Reference).Msg("reservation referencing another one") - // first let make sure both are the same - if !bytes.Equal(oldRes.Data, r.Data) { //TODO: handle network - return fmt.Errorf("trying to upgrade workloads to new version. new workload content is different from the old one. upgrade refused") + if string(oldRes.Type) != "network" { + // first let make sure both are the same + if !bytes.Equal(oldRes.Data, r.Data) { + return fmt.Errorf("trying to upgrade workloads to new version. new workload content is different from the old one. upgrade refused") + } + } else { + //TODO: handle network } // remove the old one from the cache and store the new one From 07e455fb5a982b924999aa03625c9ee8ad00409c Mon Sep 17 00:00:00 2001 From: Christophe de Carvalho Date: Thu, 30 Jul 2020 13:43:49 +0200 Subject: [PATCH 3/4] networkd: make network namespace creation idempotent when container join network --- pkg/network/nr/container.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/network/nr/container.go b/pkg/network/nr/container.go index 55f4655bd..5899e9525 100644 --- a/pkg/network/nr/container.go +++ b/pkg/network/nr/container.go @@ -30,7 +30,13 @@ func (nr *NetResource) Join(containerID string, addrs []net.IP, publicIP6 bool) } join.Namespace = containerID - netspace, err := namespace.Create(containerID) + + var netspace ns.NetNS + if namespace.Exists(containerID) { + netspace, err = namespace.GetByName(containerID) + } else { + netspace, err = namespace.Create(containerID) + } if err != nil { return join, err } From c9a77c7fc43d56939319e9bf843c4f89b17613fe Mon Sep 17 00:00:00 2001 From: Christophe de Carvalho Date: Thu, 30 Jul 2020 15:00:34 +0200 Subject: [PATCH 4/4] fix for linter --- pkg/provision/engine.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/provision/engine.go b/pkg/provision/engine.go index 2fdc40638..b1fb21c82 100644 --- a/pkg/provision/engine.go +++ b/pkg/provision/engine.go @@ -342,13 +342,11 @@ func (e *Engine) migrateToPool(ctx context.Context, r *Reservation) error { log.Info().Str("reference", r.Reference).Msg("reservation referencing another one") - if string(oldRes.Type) != "network" { + if string(oldRes.Type) != "network" { //we skip network cause its a PITA // first let make sure both are the same if !bytes.Equal(oldRes.Data, r.Data) { return fmt.Errorf("trying to upgrade workloads to new version. new workload content is different from the old one. upgrade refused") } - } else { - //TODO: handle network } // remove the old one from the cache and store the new one