kata-containers/runtime/patches/0050-runtime-add-kata-network-upate-iface-subcommand.patch
holyfei c709612f2a kata-containers: modify kata-containers version
Fix #I4KI81
reason: modify kata-containers version and update
it to 1.11.1

Signed-off-by: holyfei <yangfeiyu20092010@163.com>
2021-11-30 20:08:25 +08:00

359 lines
13 KiB
Diff

From f943e5d91f6922c599b46727e2dfd5e8e7e5bea8 Mon Sep 17 00:00:00 2001
From: jiangpengfei <jiangpengfei9@huawei.com>
Date: Wed, 19 Aug 2020 22:43:54 +0800
Subject: [PATCH 50/50] runtime: add kata-network upate-iface subcommand
reason: add kata-network update-iface subcommand to
update the exist interface in the Kata VM.
Signed-off-by: jiangpengfei <jiangpengfei9@huawei.com>
---
cli/network.go | 37 +++++++++-
virtcontainers/api.go | 25 +++++--
virtcontainers/implementation.go | 5 ++
virtcontainers/interfaces.go | 1 +
virtcontainers/pkg/vcmock/mock.go | 8 +++
virtcontainers/pkg/vcmock/types.go | 1 +
virtcontainers/sandbox.go | 137 +++++++++++++++++++++++++++++++++++++
7 files changed, 207 insertions(+), 7 deletions(-)
diff --git a/cli/network.go b/cli/network.go
index 3dd0971e..7dce0528 100644
--- a/cli/network.go
+++ b/cli/network.go
@@ -65,8 +65,9 @@ var addIfaceCommand = cli.Command{
"hwAddr":"<mac>",
"linkType":"tap",
"vhostUserSocket":"<path>"
+ "queues":<queues>
}
- device,name,mtu,hwAddr are required, IPAddresses and vhostUserSocket are optional.
+ device,name,mtu,hwAddr are required, IPAddresses, queues and vhostUserSocket are optional.
`,
Flags: []cli.Flag{},
Action: func(context *cli.Context) error {
@@ -104,6 +105,34 @@ var delIfaceCommand = cli.Command{
},
}
+var updateIfaceCommand = cli.Command{
+ Name: "update-iface",
+ Usage: "update the interface in container",
+ ArgsUsage: `update-iface <container-id> file or - for stdin
+ file or stdin for example:
+ {
+ "device":"",
+ "name":"<interface-name>",
+ "IPAddresses":[{"address":"<ip>","mask":"<mask>"}],
+ "mtu":0,
+ "hwAddr":"",
+ "linkType":"",
+ "vhostUserSocket":"",
+ "queues":0
+ }
+ name is required,IPAddresses is optional,device,mtu,hwAddr,linkType,queues and vhostUserSocket should be 0 or empty.
+ `,
+ Flags: []cli.Flag{},
+ Action: func(context *cli.Context) error {
+ ctx, err := cliContextToContext(context)
+ if err != nil {
+ return err
+ }
+
+ return networkModifyCommand(ctx, context.Args().First(), context.Args().Get(1), interfaceType, vcTypes.NetworkOpUpdate)
+ },
+}
+
var listIfacesCommand = cli.Command{
Name: "list-ifaces",
Usage: "list network interfaces in a container",
@@ -262,6 +291,12 @@ func networkModifyCommand(ctx context.Context, containerID, input string, opType
kataLog.WithField("resulting-interface", fmt.Sprintf("%+v", resultingInf)).
WithError(err).Error("delete interface failed")
}
+ case vcTypes.NetworkOpUpdate:
+ resultingInf, err = vci.UpdateInterface(ctx, sandboxID, inf)
+ if err != nil {
+ kataLog.WithField("resulting-interface", fmt.Sprintf("%+v", resultingInf)).
+ WithError(err).Error("update interface failed")
+ }
}
json.NewEncoder(output).Encode(resultingInf)
diff --git a/virtcontainers/api.go b/virtcontainers/api.go
index 7036df8c..ca5412a9 100644
--- a/virtcontainers/api.go
+++ b/virtcontainers/api.go
@@ -889,7 +889,7 @@ func AddDevice(ctx context.Context, sandboxID string, info deviceConfig.DeviceIn
return s.AddDevice(info)
}
-func toggleInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface, add bool) (*vcTypes.Interface, error) {
+func toggleInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface, op vcTypes.NetworkOp) (*vcTypes.Interface, error) {
if sandboxID == "" {
return nil, vcTypes.ErrNeedSandboxID
}
@@ -906,11 +906,16 @@ func toggleInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interfa
}
defer s.releaseStatelessSandbox()
- if add {
+ switch op {
+ case vcTypes.NetworkOpAdd:
return s.AddInterface(inf)
+ case vcTypes.NetworkOpRemove:
+ return s.RemoveInterface(inf)
+ case vcTypes.NetworkOpUpdate:
+ return s.UpdateInterface(inf)
+ default:
+ return nil, fmt.Errorf("operation is not found")
}
-
- return s.RemoveInterface(inf)
}
// AddInterface is the virtcontainers add interface entry point.
@@ -918,7 +923,7 @@ func AddInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface)
span, ctx := trace(ctx, "AddInterface")
defer span.Finish()
- return toggleInterface(ctx, sandboxID, inf, true)
+ return toggleInterface(ctx, sandboxID, inf, vcTypes.NetworkOpAdd)
}
// RemoveInterface is the virtcontainers remove interface entry point.
@@ -926,7 +931,15 @@ func RemoveInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interfa
span, ctx := trace(ctx, "RemoveInterface")
defer span.Finish()
- return toggleInterface(ctx, sandboxID, inf, false)
+ return toggleInterface(ctx, sandboxID, inf, vcTypes.NetworkOpRemove)
+}
+
+// UpdateInterface updates interface entry point in the virtcontainers.
+func UpdateInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error) {
+ span, ctx := trace(ctx, "UpdateInterface")
+ defer span.Finish()
+
+ return toggleInterface(ctx, sandboxID, inf, vcTypes.NetworkOpUpdate)
}
// ListInterfaces is the virtcontainers list interfaces entry point.
diff --git a/virtcontainers/implementation.go b/virtcontainers/implementation.go
index 0265d1ed..e4bc4ae6 100644
--- a/virtcontainers/implementation.go
+++ b/virtcontainers/implementation.go
@@ -163,6 +163,11 @@ func (impl *VCImpl) ListInterfaces(ctx context.Context, sandboxID string) ([]*vc
return ListInterfaces(ctx, sandboxID)
}
+// ListInterfaces implements the VC function of the same name.
+func (impl *VCImpl) UpdateInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error) {
+ return UpdateInterface(ctx, sandboxID, inf)
+}
+
// UpdateRoutes implements the VC function of the same name.
func (impl *VCImpl) UpdateRoutes(ctx context.Context, sandboxID string, routes []*vcTypes.Route, op vcTypes.NetworkOp) ([]*vcTypes.Route, error) {
return UpdateRoutes(ctx, sandboxID, routes, op)
diff --git a/virtcontainers/interfaces.go b/virtcontainers/interfaces.go
index d8f0be69..0fd12d84 100644
--- a/virtcontainers/interfaces.go
+++ b/virtcontainers/interfaces.go
@@ -51,6 +51,7 @@ type VC interface {
AddInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
RemoveInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
+ UpdateInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
ListInterfaces(ctx context.Context, sandboxID string) ([]*vcTypes.Interface, error)
UpdateRoutes(ctx context.Context, sandboxID string, routes []*vcTypes.Route, op vcTypes.NetworkOp) ([]*vcTypes.Route, error)
ListRoutes(ctx context.Context, sandboxID string) ([]*vcTypes.Route, error)
diff --git a/virtcontainers/pkg/vcmock/mock.go b/virtcontainers/pkg/vcmock/mock.go
index aa9bae9a..d3bf201f 100644
--- a/virtcontainers/pkg/vcmock/mock.go
+++ b/virtcontainers/pkg/vcmock/mock.go
@@ -273,6 +273,14 @@ func (m *VCMock) ListInterfaces(ctx context.Context, sandboxID string) ([]*vcTyp
return nil, fmt.Errorf("%s: %s (%+v): sandboxID: %v", mockErrorPrefix, getSelf(), m, sandboxID)
}
+// UpdateInterface implements the VC function of the same name
+func (m *VCMock) UpdateInterface(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error) {
+ if m.UpdateRoutesFunc != nil {
+ return m.UpdateInterfaceFunc(ctx, sandboxID, inf)
+ }
+ return nil, fmt.Errorf("%s: %s (%+v): sandboxID: %v", mockErrorPrefix, getSelf(), m, sandboxID)
+}
+
// UpdateRoutes implements the VC function of the same name.
func (m *VCMock) UpdateRoutes(ctx context.Context, sandboxID string, routes []*vcTypes.Route, op vcTypes.NetworkOp) ([]*vcTypes.Route, error) {
if m.UpdateRoutesFunc != nil {
diff --git a/virtcontainers/pkg/vcmock/types.go b/virtcontainers/pkg/vcmock/types.go
index 610b4602..152e66b7 100644
--- a/virtcontainers/pkg/vcmock/types.go
+++ b/virtcontainers/pkg/vcmock/types.go
@@ -73,6 +73,7 @@ type VCMock struct {
AddInterfaceFunc func(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
RemoveInterfaceFunc func(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
ListInterfacesFunc func(ctx context.Context, sandboxID string) ([]*vcTypes.Interface, error)
+ UpdateInterfaceFunc func(ctx context.Context, sandboxID string, inf *vcTypes.Interface) (*vcTypes.Interface, error)
UpdateRoutesFunc func(ctx context.Context, sandboxID string, routes []*vcTypes.Route) ([]*vcTypes.Route, error)
ListRoutesFunc func(ctx context.Context, sandboxID string) ([]*vcTypes.Route, error)
CleanupContainerFunc func(ctx context.Context, sandboxID, containerID string, force bool) error
diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go
index d8ab6c1a..174e6cb6 100644
--- a/virtcontainers/sandbox.go
+++ b/virtcontainers/sandbox.go
@@ -1031,6 +1031,54 @@ func (s *Sandbox) RemoveInterface(inf *vcTypes.Interface) (*vcTypes.Interface, e
return nil, nil
}
+// UpdateInterface updates the nic.
+func (s *Sandbox) UpdateInterface(inf *vcTypes.Interface) (*vcTypes.Interface, error) {
+ err := checkUpdateInterfaceInfo(inf)
+ if err != nil {
+ return nil, err
+ }
+
+ nicInGuest := false
+
+ endpoint := s.getEndpointByName(inf.Name)
+ // nic is not in local endpoints
+ if endpoint == nil {
+ interfaceInGuestInf := s.getInterfaceInfByName(inf.Name)
+ if interfaceInGuestInf == nil {
+ return nil, fmt.Errorf("can not find the network interface")
+ }
+
+ nicInGuest = true
+ endpoint, err = s.generateEndpointForStore(interfaceInGuestInf)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // update endpoint ip
+ err = s.updateEndpointIP(endpoint, inf)
+ if err != nil {
+ return nil, err
+ }
+
+ s.Logger().WithField("endpoint-type", endpoint.Type()).Info("Update endpoint")
+ grpcIf, err := s.agent.updateInterface(inf)
+ if err != nil {
+ return nil, err
+ }
+
+ if nicInGuest {
+ s.networkNS.Endpoints = append(s.networkNS.Endpoints, endpoint)
+ }
+
+ if err = s.Save(); err != nil {
+ s.Logger().WithError(err).Error("failed to store the network information")
+ return nil, err
+ }
+
+ return grpcIf, nil
+}
+
// ListInterfaces lists all nics and their configurations in the sandbox.
func (s *Sandbox) ListInterfaces() ([]*vcTypes.Interface, error) {
return s.agent.listInterfaces()
@@ -2431,6 +2479,95 @@ func (s *Sandbox) IsCompatOldCNI() bool {
return s.config.NetworkConfig.EnableCompatOldCNI
}
+func checkUpdateInterfaceInfo(inf *vcTypes.Interface) error {
+ if inf.Mtu > 0 || inf.Queues > 0 || inf.Device != "" || inf.VhostUserSocket != "" || inf.LinkType != "" || inf.HwAddr != "" {
+ return fmt.Errorf("device,mtu,hwAddr,linkType,queues and vhostUserSocket should be 0 or empty")
+ }
+
+ return nil
+}
+
+// getEndpointByName returns the endpoint by name.
+func (s *Sandbox) getEndpointByName(name string) Endpoint {
+ if name == "" {
+ return nil
+ }
+
+ for i, endpoint := range s.networkNS.Endpoints {
+ if endpoint.Name() == name {
+ return s.networkNS.Endpoints[i]
+ }
+ }
+
+ return nil
+}
+
+// getInterfaceInfByName returns the interface information.
+func (s *Sandbox) getInterfaceInfByName(name string) *vcTypes.Interface {
+ if name == "" {
+ return nil
+ }
+
+ nics, err := s.agent.listInterfaces()
+ if err != nil {
+ return nil
+ }
+
+ for _, i := range nics {
+ if i.Name == name {
+ return i
+ }
+ }
+
+ return nil
+}
+
+// generateEndpointForStore only generates endpoint information for store,it does not create a endpoint
+func (s *Sandbox) generateEndpointForStore(inf *vcTypes.Interface) (*TapEndpoint, error) {
+ netInfo, err := s.generateNetInfo(inf)
+ if err != nil {
+ return nil, err
+ }
+
+ endpoint := &TapEndpoint{
+ TapInterface: TapInterface{
+ Name: inf.Name,
+ TAPIface: NetworkInterface{
+ HardAddr: inf.HwAddr,
+ },
+ },
+ EndpointType: TapEndpointType,
+ }
+
+ endpoint.SetProperties(netInfo)
+
+ return endpoint, nil
+}
+
+func (s *Sandbox) updateEndpointIP(endpoint Endpoint, inf *vcTypes.Interface) error {
+ if endpoint == nil {
+ return fmt.Errorf("endpoint is nil")
+ }
+
+ netInfo := endpoint.Properties()
+
+ var addrs []netlink.Addr
+ for _, addr := range inf.IPAddresses {
+ netlinkAddrStr := fmt.Sprintf("%s/%s", addr.Address, addr.Mask)
+ netlinkAddr, err := netlink.ParseAddr(netlinkAddrStr)
+ if err != nil {
+ return fmt.Errorf("could not parse %q: %v", netlinkAddrStr, err)
+ }
+
+ addrs = append(addrs, *netlinkAddr)
+ }
+
+ netInfo.Addrs = addrs
+ endpoint.SetProperties(netInfo)
+
+ return nil
+}
+
// updateStaticSandboxResources update sandbox's cpu and memory resource passed by
// sandbox_cpu and sandbox_mem annotations
func updateStaticSandboxResources(sandboxConfig *SandboxConfig) error {
--
2.14.3 (Apple Git-98)