From d83c10343716791336ba2cef382c26e6af861d61 Mon Sep 17 00:00:00 2001 From: Richard Case <198425+richardcase@users.noreply.github.com> Date: Tue, 12 Jul 2022 11:09:19 +0100 Subject: [PATCH] fix: tap interface attach to bridge (#479) When requesting that a tap device is added to a microvm then we should attach (i.e. set the master) to a bridge. The bridge will be supplied via a new bridge-name flag. And the attach should not be done for the mmds network interface. The grpc api has been updated to allow the consumer to specify a bridge-name that is different as part of the create microvm call. Signed-off-by: Richard Case --- .../microvm/v1alpha1/microvms.swagger.json | 14 + api/types/microvm.pb.go | 344 +++++++++++------- api/types/microvm.proto | 10 + buf.lock | 2 +- core/errors/errors.go | 33 +- core/models/network.go | 4 +- core/ports/services.go | 4 + core/steps/network/interface_create.go | 6 + core/steps/network/interface_create_test.go | 9 +- core/steps/network/interface_delete_test.go | 4 +- go.mod | 7 +- go.sum | 5 + infrastructure/grpc/convert.go | 3 + infrastructure/network/network_service.go | 39 +- internal/command/flags/flags.go | 9 +- internal/command/run/run.go | 5 + internal/config/config.go | 2 + internal/inject/wire.go | 1 + internal/inject/wire_gen.go | 4 +- userdocs/docs/grpc/types/proto.md | 17 + 20 files changed, 357 insertions(+), 165 deletions(-) diff --git a/api/services/microvm/v1alpha1/microvms.swagger.json b/api/services/microvm/v1alpha1/microvms.swagger.json index c3189b10..4eaf422c 100644 --- a/api/services/microvm/v1alpha1/microvms.swagger.json +++ b/api/services/microvm/v1alpha1/microvms.swagger.json @@ -404,6 +404,10 @@ "address": { "$ref": "#/definitions/typesStaticAddress", "description": "Address is an optional static IP address to manually assign to this interface. \nIf not supplied then DHCP will be used." + }, + "overrides": { + "$ref": "#/definitions/typesNetworkOverrides", + "description": "Overrides is optional overrides applicable for network configuration." } } }, @@ -425,6 +429,16 @@ } } }, + "typesNetworkOverrides": { + "type": "object", + "properties": { + "bridgeName": { + "type": "string", + "description": "BridgeName is the name of the Linux bridge to attach TAP devices to. This overrides\nany value set at the overall flintlock level." + } + }, + "description": "NetworkOverrides represents override values for a network interface." + }, "typesStaticAddress": { "type": "object", "properties": { diff --git a/api/types/microvm.pb.go b/api/types/microvm.pb.go index 0952a76d..a2b3d230 100644 --- a/api/types/microvm.pb.go +++ b/api/types/microvm.pb.go @@ -566,6 +566,8 @@ type NetworkInterface struct { // Address is an optional static IP address to manually assign to this interface. // If not supplied then DHCP will be used. Address *StaticAddress `protobuf:"bytes,5,opt,name=address,proto3,oneof" json:"address,omitempty"` + // Overrides is optional overrides applicable for network configuration. + Overrides *NetworkOverrides `protobuf:"bytes,6,opt,name=overrides,proto3,oneof" json:"overrides,omitempty"` } func (x *NetworkInterface) Reset() { @@ -628,6 +630,13 @@ func (x *NetworkInterface) GetAddress() *StaticAddress { return nil } +func (x *NetworkInterface) GetOverrides() *NetworkOverrides { + if x != nil { + return x.Overrides + } + return nil +} + // StaticAddress represents a static IPv4 or IPv6 address. type StaticAddress struct { state protoimpl.MessageState @@ -1146,6 +1155,56 @@ func (x *NetworkInterfaceStatus) GetMacAddress() string { return "" } +// NetworkOverrides represents override values for a network interface. +type NetworkOverrides struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // BridgeName is the name of the Linux bridge to attach TAP devices to. This overrides + // any value set at the overall flintlock level. + BridgeName *string `protobuf:"bytes,1,opt,name=bridge_name,json=bridgeName,proto3,oneof" json:"bridge_name,omitempty"` +} + +func (x *NetworkOverrides) Reset() { + *x = NetworkOverrides{} + if protoimpl.UnsafeEnabled { + mi := &file_types_microvm_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkOverrides) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkOverrides) ProtoMessage() {} + +func (x *NetworkOverrides) ProtoReflect() protoreflect.Message { + mi := &file_types_microvm_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkOverrides.ProtoReflect.Descriptor instead. +func (*NetworkOverrides) Descriptor() ([]byte, []int) { + return file_types_microvm_proto_rawDescGZIP(), []int{13} +} + +func (x *NetworkOverrides) GetBridgeName() string { + if x != nil && x.BridgeName != nil { + return *x.BridgeName + } + return "" +} + var File_types_microvm_proto protoreflect.FileDescriptor var file_types_microvm_proto_rawDesc = []byte{ @@ -1238,7 +1297,7 @@ var file_types_microvm_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, - 0x0a, 0x09, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x8e, 0x02, 0x0a, 0x10, + 0x0a, 0x09, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xe2, 0x02, 0x0a, 0x10, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3f, 0x0a, @@ -1251,107 +1310,117 @@ var file_types_microvm_proto_rawDesc = []byte{ 0x12, 0x3d, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x22, - 0x21, 0x0a, 0x09, 0x49, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, - 0x4d, 0x41, 0x43, 0x56, 0x54, 0x41, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x50, - 0x10, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x63, - 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x76, 0x0a, 0x0d, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x67, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x22, 0xe2, 0x01, 0x0a, 0x06, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, - 0x79, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x62, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08, 0x73, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x4d, 0x62, - 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, - 0x5f, 0x6d, 0x62, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x53, 0x0a, 0x0c, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x10, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x2d, - 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x99, 0x05, - 0x0a, 0x0d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, - 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, - 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0c, 0x6b, 0x65, 0x72, - 0x6e, 0x65, 0x6c, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0b, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x72, 0x64, 0x5f, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x6c, 0x69, - 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x72, 0x64, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x64, 0x0a, 0x12, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x66, 0x6c, - 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x69, - 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x1a, 0x59, 0x0a, 0x0c, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, - 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x16, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x42, 0x0a, 0x0c, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x22, 0x3c, 0x0a, 0x0c, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, 0x05, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x52, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x79, 0x0a, 0x05, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, + 0x73, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, + 0x44, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x48, 0x02, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x88, 0x01, 0x01, 0x22, 0x21, 0x0a, 0x09, 0x49, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x43, 0x56, 0x54, 0x41, 0x50, 0x10, 0x00, 0x12, + 0x07, 0x0a, 0x03, 0x54, 0x41, 0x50, 0x10, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x67, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x63, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x22, 0x76, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x42, 0x0a, 0x0a, 0x08, + 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x22, 0xe2, 0x01, 0x0a, 0x06, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, + 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x61, + 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0c, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, + 0x6d, 0x62, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08, 0x73, 0x69, 0x7a, 0x65, + 0x49, 0x6e, 0x4d, 0x62, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x70, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x62, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x53, 0x0a, + 0x0c, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2e, 0x0a, + 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, + 0x11, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, + 0x65, 0x22, 0x99, 0x05, 0x0a, 0x0d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, + 0x4d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x39, 0x0a, + 0x0c, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0b, 0x6b, 0x65, 0x72, + 0x6e, 0x65, 0x6c, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, + 0x72, 0x64, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x22, - 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x44, - 0x45, 0x56, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4f, 0x53, 0x54, 0x50, 0x41, 0x54, 0x48, - 0x10, 0x01, 0x22, 0x79, 0x0a, 0x16, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, - 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x68, 0x6f, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1f, 0x0a, 0x0b, - 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x3d, 0x5a, - 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x65, 0x61, 0x76, - 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2d, 0x6c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x6d, 0x65, 0x74, - 0x61, 0x6c, 0x2f, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x72, 0x64, 0x4d, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x12, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x74, + 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x1a, + 0x59, 0x0a, 0x0c, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x16, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x42, 0x0a, 0x0c, 0x4d, 0x69, 0x63, + 0x72, 0x6f, 0x56, 0x4d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, + 0x44, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, + 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x22, 0x3c, 0x0a, + 0x0c, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, + 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, + 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x79, 0x0a, 0x05, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x22, 0x22, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x07, 0x0a, 0x03, 0x44, 0x45, 0x56, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4f, 0x53, 0x54, + 0x50, 0x41, 0x54, 0x48, 0x10, 0x01, 0x22, 0x79, 0x0a, 0x16, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x28, 0x0a, 0x10, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x68, 0x6f, 0x73, 0x74, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x22, 0x48, 0x0a, 0x10, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0b, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x3d, 0x5a, 0x3b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x2d, 0x6c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x6d, 0x65, 0x74, 0x61, 0x6c, + 0x2f, 0x66, 0x6c, 0x69, 0x6e, 0x74, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x3b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1367,7 +1436,7 @@ func file_types_microvm_proto_rawDescGZIP() []byte { } var file_types_microvm_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_types_microvm_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_types_microvm_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_types_microvm_proto_goTypes = []interface{}{ (NetworkInterface_IfaceType)(0), // 0: flintlock.types.NetworkInterface.IfaceType (MicroVMStatus_MicroVMState)(0), // 1: flintlock.types.MicroVMStatus.MicroVMState @@ -1385,44 +1454,46 @@ var file_types_microvm_proto_goTypes = []interface{}{ (*VolumeStatus)(nil), // 13: flintlock.types.VolumeStatus (*Mount)(nil), // 14: flintlock.types.Mount (*NetworkInterfaceStatus)(nil), // 15: flintlock.types.NetworkInterfaceStatus - nil, // 16: flintlock.types.MicroVMSpec.LabelsEntry - nil, // 17: flintlock.types.MicroVMSpec.MetadataEntry - nil, // 18: flintlock.types.Kernel.CmdlineEntry - nil, // 19: flintlock.types.MicroVMStatus.VolumesEntry - nil, // 20: flintlock.types.MicroVMStatus.NetworkInterfacesEntry - (*timestamppb.Timestamp)(nil), // 21: google.protobuf.Timestamp + (*NetworkOverrides)(nil), // 16: flintlock.types.NetworkOverrides + nil, // 17: flintlock.types.MicroVMSpec.LabelsEntry + nil, // 18: flintlock.types.MicroVMSpec.MetadataEntry + nil, // 19: flintlock.types.Kernel.CmdlineEntry + nil, // 20: flintlock.types.MicroVMStatus.VolumesEntry + nil, // 21: flintlock.types.MicroVMStatus.NetworkInterfacesEntry + (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp } var file_types_microvm_proto_depIdxs = []int32{ 4, // 0: flintlock.types.MicroVM.spec:type_name -> flintlock.types.MicroVMSpec 12, // 1: flintlock.types.MicroVM.status:type_name -> flintlock.types.MicroVMStatus - 16, // 2: flintlock.types.MicroVMSpec.labels:type_name -> flintlock.types.MicroVMSpec.LabelsEntry + 17, // 2: flintlock.types.MicroVMSpec.labels:type_name -> flintlock.types.MicroVMSpec.LabelsEntry 5, // 3: flintlock.types.MicroVMSpec.kernel:type_name -> flintlock.types.Kernel 6, // 4: flintlock.types.MicroVMSpec.initrd:type_name -> flintlock.types.Initrd 9, // 5: flintlock.types.MicroVMSpec.root_volume:type_name -> flintlock.types.Volume 9, // 6: flintlock.types.MicroVMSpec.additional_volumes:type_name -> flintlock.types.Volume 7, // 7: flintlock.types.MicroVMSpec.interfaces:type_name -> flintlock.types.NetworkInterface - 17, // 8: flintlock.types.MicroVMSpec.metadata:type_name -> flintlock.types.MicroVMSpec.MetadataEntry - 21, // 9: flintlock.types.MicroVMSpec.created_at:type_name -> google.protobuf.Timestamp - 21, // 10: flintlock.types.MicroVMSpec.updated_at:type_name -> google.protobuf.Timestamp - 21, // 11: flintlock.types.MicroVMSpec.deleted_at:type_name -> google.protobuf.Timestamp - 18, // 12: flintlock.types.Kernel.cmdline:type_name -> flintlock.types.Kernel.CmdlineEntry + 18, // 8: flintlock.types.MicroVMSpec.metadata:type_name -> flintlock.types.MicroVMSpec.MetadataEntry + 22, // 9: flintlock.types.MicroVMSpec.created_at:type_name -> google.protobuf.Timestamp + 22, // 10: flintlock.types.MicroVMSpec.updated_at:type_name -> google.protobuf.Timestamp + 22, // 11: flintlock.types.MicroVMSpec.deleted_at:type_name -> google.protobuf.Timestamp + 19, // 12: flintlock.types.Kernel.cmdline:type_name -> flintlock.types.Kernel.CmdlineEntry 0, // 13: flintlock.types.NetworkInterface.type:type_name -> flintlock.types.NetworkInterface.IfaceType 8, // 14: flintlock.types.NetworkInterface.address:type_name -> flintlock.types.StaticAddress - 10, // 15: flintlock.types.Volume.source:type_name -> flintlock.types.VolumeSource - 1, // 16: flintlock.types.MicroVMStatus.state:type_name -> flintlock.types.MicroVMStatus.MicroVMState - 19, // 17: flintlock.types.MicroVMStatus.volumes:type_name -> flintlock.types.MicroVMStatus.VolumesEntry - 14, // 18: flintlock.types.MicroVMStatus.kernel_mount:type_name -> flintlock.types.Mount - 14, // 19: flintlock.types.MicroVMStatus.initrd_mount:type_name -> flintlock.types.Mount - 20, // 20: flintlock.types.MicroVMStatus.network_interfaces:type_name -> flintlock.types.MicroVMStatus.NetworkInterfacesEntry - 14, // 21: flintlock.types.VolumeStatus.mount:type_name -> flintlock.types.Mount - 2, // 22: flintlock.types.Mount.type:type_name -> flintlock.types.Mount.MountType - 13, // 23: flintlock.types.MicroVMStatus.VolumesEntry.value:type_name -> flintlock.types.VolumeStatus - 15, // 24: flintlock.types.MicroVMStatus.NetworkInterfacesEntry.value:type_name -> flintlock.types.NetworkInterfaceStatus - 25, // [25:25] is the sub-list for method output_type - 25, // [25:25] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 16, // 15: flintlock.types.NetworkInterface.overrides:type_name -> flintlock.types.NetworkOverrides + 10, // 16: flintlock.types.Volume.source:type_name -> flintlock.types.VolumeSource + 1, // 17: flintlock.types.MicroVMStatus.state:type_name -> flintlock.types.MicroVMStatus.MicroVMState + 20, // 18: flintlock.types.MicroVMStatus.volumes:type_name -> flintlock.types.MicroVMStatus.VolumesEntry + 14, // 19: flintlock.types.MicroVMStatus.kernel_mount:type_name -> flintlock.types.Mount + 14, // 20: flintlock.types.MicroVMStatus.initrd_mount:type_name -> flintlock.types.Mount + 21, // 21: flintlock.types.MicroVMStatus.network_interfaces:type_name -> flintlock.types.MicroVMStatus.NetworkInterfacesEntry + 14, // 22: flintlock.types.VolumeStatus.mount:type_name -> flintlock.types.Mount + 2, // 23: flintlock.types.Mount.type:type_name -> flintlock.types.Mount.MountType + 13, // 24: flintlock.types.MicroVMStatus.VolumesEntry.value:type_name -> flintlock.types.VolumeStatus + 15, // 25: flintlock.types.MicroVMStatus.NetworkInterfacesEntry.value:type_name -> flintlock.types.NetworkInterfaceStatus + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_types_microvm_proto_init() } @@ -1587,6 +1658,18 @@ func file_types_microvm_proto_init() { return nil } } + file_types_microvm_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkOverrides); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_types_microvm_proto_msgTypes[1].OneofWrappers = []interface{}{} file_types_microvm_proto_msgTypes[2].OneofWrappers = []interface{}{} @@ -1595,13 +1678,14 @@ func file_types_microvm_proto_init() { file_types_microvm_proto_msgTypes[5].OneofWrappers = []interface{}{} file_types_microvm_proto_msgTypes[6].OneofWrappers = []interface{}{} file_types_microvm_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_types_microvm_proto_msgTypes[13].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_types_microvm_proto_rawDesc, NumEnums: 3, - NumMessages: 18, + NumMessages: 19, NumExtensions: 0, NumServices: 0, }, diff --git a/api/types/microvm.proto b/api/types/microvm.proto index 4427dab7..f9379028 100644 --- a/api/types/microvm.proto +++ b/api/types/microvm.proto @@ -110,6 +110,9 @@ message NetworkInterface { // Address is an optional static IP address to manually assign to this interface. // If not supplied then DHCP will be used. optional StaticAddress address = 5; + // Overrides is optional overrides applicable for network configuration. + optional NetworkOverrides overrides = 6; + } // StaticAddress represents a static IPv4 or IPv6 address. @@ -201,3 +204,10 @@ message NetworkInterfaceStatus { // MACAddress is the MAC address of the host interface. string mac_address = 3; } + +// NetworkOverrides represents override values for a network interface. +message NetworkOverrides { + // BridgeName is the name of the Linux bridge to attach TAP devices to. This overrides + // any value set at the overall flintlock level. + optional string bridge_name = 1; +} diff --git a/buf.lock b/buf.lock index 3a96b622..80ce3428 100644 --- a/buf.lock +++ b/buf.lock @@ -4,7 +4,7 @@ deps: - remote: buf.build owner: googleapis repository: googleapis - commit: 86d30bdfc34044fb9339e1bd9673839b + commit: 2646de1347094058879360e68cb2ccc6 - remote: buf.build owner: grpc-ecosystem repository: grpc-gateway diff --git a/core/errors/errors.go b/core/errors/errors.go index bfba3e8f..483a795f 100644 --- a/core/errors/errors.go +++ b/core/errors/errors.go @@ -6,22 +6,23 @@ import ( ) var ( - ErrSpecRequired = errors.New("microvm spec is required") - ErrVMIDRequired = errors.New("id for microvm is required") - ErrNameRequired = errors.New("name is required") - ErrUIDRequired = errors.New("uid is required") - ErrNamespaceRequired = errors.New("namespace is required") - ErrKernelImageRequired = errors.New("kernel image is required") - ErrVolumeRequired = errors.New("no volumes specified, at least 1 volume is required") - ErrRootVolumeRequired = errors.New("a root volume is required") - ErrNoMount = errors.New("no image mount point") - ErrNoVolumeMount = errors.New("no volume mount point") - ErrParentIfaceRequired = errors.New("a parent network device name is required") - ErrGuestDeviceNameRequired = errors.New("a guest device name is required") - ErrUnsupportedIfaceType = errors.New("unsupported network interface type") - ErrIfaceNotFound = errors.New("network interface not found") - ErrMissingStatusInfo = errors.New("status is not defined") - ErrUnableToBoot = errors.New("microvm is unable to boot") + ErrSpecRequired = errors.New("microvm spec is required") + ErrVMIDRequired = errors.New("id for microvm is required") + ErrNameRequired = errors.New("name is required") + ErrUIDRequired = errors.New("uid is required") + ErrNamespaceRequired = errors.New("namespace is required") + ErrKernelImageRequired = errors.New("kernel image is required") + ErrVolumeRequired = errors.New("no volumes specified, at least 1 volume is required") + ErrRootVolumeRequired = errors.New("a root volume is required") + ErrNoMount = errors.New("no image mount point") + ErrNoVolumeMount = errors.New("no volume mount point") + ErrParentIfaceRequiredForMacvtap = errors.New("a parent network device name is required for macvtap interfaces") + ErrParentIfaceRequiredForAttachingTap = errors.New("a parent network device name is required for attaching a TAP interface") + ErrGuestDeviceNameRequired = errors.New("a guest device name is required") + ErrUnsupportedIfaceType = errors.New("unsupported network interface type") + ErrIfaceNotFound = errors.New("network interface not found") + ErrMissingStatusInfo = errors.New("status is not defined") + ErrUnableToBoot = errors.New("microvm is unable to boot") ) // TopicNotFoundError is an error created when a topic with a specific name isn't found. diff --git a/core/models/network.go b/core/models/network.go index 7a2acfdd..ef02dda0 100644 --- a/core/models/network.go +++ b/core/models/network.go @@ -23,7 +23,9 @@ type NetworkInterface struct { Type IfaceType `json:"type" validate:"oneof=tap macvtap unsupported"` // StaticAddress is an optional static IP address to assign to this interface. // If not supplied then DHCP will be used. - StaticAddress *StaticAddress `json:"staticAddress,omitempty"` + StaticAddress *StaticAddress `json:"staticAddrss,omitempty"` + // BridgeName is the name of the Linux bridge to attach the TAP device to. + BridgeName string `json:"branch_name,omitempty"` } // StaticAddress specifies a static IP address configuration. diff --git a/core/ports/services.go b/core/ports/services.go index f5514b92..f7d88025 100644 --- a/core/ports/services.go +++ b/core/ports/services.go @@ -124,6 +124,10 @@ type IfaceCreateInput struct { // MAC allows the specifying of a specific MAC address to use for the interface. If // not supplied a autogenerated MAC address will be used. MAC string + // Attach indicates if this device should be attached to the parent bridge. Only applicable to TAP devices. + Attach bool + // BridgeName is the name of the bridge to attach to. Only if this is a tap device and attach is true. + BridgeName string } type IfaceDetails struct { diff --git a/core/steps/network/interface_create.go b/core/steps/network/interface_create.go index 979430fb..fc5e78ea 100644 --- a/core/steps/network/interface_create.go +++ b/core/steps/network/interface_create.go @@ -109,6 +109,12 @@ func (s *createInterface) Do(ctx context.Context) ([]planner.Procedure, error) { DeviceName: deviceName, Type: s.iface.Type, MAC: s.iface.GuestMAC, + Attach: true, + BridgeName: s.iface.BridgeName, + } + + if s.iface.Type == models.IfaceTypeTap && s.iface.AllowMetadataRequests { + input.Attach = false } output, err := s.svc.IfaceCreate(ctx, *input) diff --git a/core/steps/network/interface_create_test.go b/core/steps/network/interface_create_test.go index 4d30f6f2..068323e3 100644 --- a/core/steps/network/interface_create_test.go +++ b/core/steps/network/interface_create_test.go @@ -211,6 +211,7 @@ func TestNewNetworkInterface_missingInterface(t *testing.T) { IfaceCreate(gomock.Eq(ctx), gomock.Eq(ports.IfaceCreateInput{ DeviceName: expectedTapDeviceName, MAC: defaultMACAddress, + Attach: true, })). Return(&ports.IfaceDetails{ DeviceName: expectedTapDeviceName, @@ -239,7 +240,7 @@ func TestNewNetworkInterface_svcError(t *testing.T) { svc.EXPECT(). IfaceExists(gomock.Eq(ctx), gomock.Eq(expectedTapDeviceName)). - Return(false, errors.ErrParentIfaceRequired). + Return(false, errors.ErrParentIfaceRequiredForAttachingTap). Times(2) step := network.NewNetworkInterface(vmid, iface, status, svc) @@ -249,7 +250,7 @@ func TestNewNetworkInterface_svcError(t *testing.T) { g.Expect(shouldDo).To(g.BeFalse()) _, err = step.Do(ctx) - g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequired)) + g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequiredForAttachingTap)) verifyErr := step.Verify(ctx) g.Expect(verifyErr).To(g.BeNil()) @@ -322,11 +323,11 @@ func TestNewNetworkInterface_createError(t *testing.T) { svc.EXPECT(). IfaceCreate(gomock.Eq(ctx), &ifaceCreateInputMatcher{}). - Return(nil, errors.ErrParentIfaceRequired). + Return(nil, errors.ErrParentIfaceRequiredForAttachingTap). Times(1) _, err = step.Do(ctx) - g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequired)) + g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequiredForAttachingTap)) verifyErr := step.Verify(ctx) g.Expect(verifyErr).To(g.BeNil()) diff --git a/core/steps/network/interface_delete_test.go b/core/steps/network/interface_delete_test.go index e6c023c7..ea0164c2 100644 --- a/core/steps/network/interface_delete_test.go +++ b/core/steps/network/interface_delete_test.go @@ -169,7 +169,7 @@ func TestDeleteNetworkInterface_IfaceExistsError(t *testing.T) { svc.EXPECT(). IfaceExists(gomock.Eq(ctx), gomock.Eq(expectedTapDeviceName)). - Return(false, errors.ErrParentIfaceRequired). + Return(false, errors.ErrParentIfaceRequiredForAttachingTap). Times(2) step := network.DeleteNetworkInterface(vmid, iface, svc) @@ -179,7 +179,7 @@ func TestDeleteNetworkInterface_IfaceExistsError(t *testing.T) { g.Expect(shouldDo).To(g.BeFalse()) _, err = step.Do(ctx) - g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequired)) + g.Expect(err).To(g.MatchError(errors.ErrParentIfaceRequiredForAttachingTap)) verifyErr := step.Verify(ctx) g.Expect(verifyErr).To(g.BeNil()) diff --git a/go.mod b/go.mod index 4fd1cb1a..e72e940c 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,6 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/urfave/cli/v2 v2.10.3 - github.com/weaveworks-liquidmetal/flintlock/api v0.0.0-20211217111250-5f8d70c4a581 github.com/weaveworks-liquidmetal/flintlock/client v0.0.0-00010101000000-000000000000 github.com/yitsushi/file-tailor v1.0.0 sigs.k8s.io/yaml v1.3.0 @@ -84,6 +83,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/google/subcommands v1.0.1 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-multierror v1.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -102,6 +102,7 @@ require ( github.com/opencontainers/selinux v1.8.2 // indirect github.com/pelletier/go-toml/v2 v2.0.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect @@ -110,13 +111,17 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect + github.com/weaveworks-liquidmetal/flintlock/api v0.0.0-20220628141946-264f4544f49f // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.mongodb.org/mongo-driver v1.7.5 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/mod v0.4.2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.1 // indirect + golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect diff --git a/go.sum b/go.sum index e3a00711..8638f046 100644 --- a/go.sum +++ b/go.sum @@ -512,6 +512,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -974,6 +975,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1216,11 +1218,14 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= diff --git a/infrastructure/grpc/convert.go b/infrastructure/grpc/convert.go index 3292aed4..1b436b05 100644 --- a/infrastructure/grpc/convert.go +++ b/infrastructure/grpc/convert.go @@ -108,6 +108,9 @@ func convertNetworkInterfaceToModel(netInt *types.NetworkInterface) *models.Netw converted.StaticAddress.Nameservers = append(converted.StaticAddress.Nameservers, nameserver) } } + if netInt.Overrides != nil { + converted.BridgeName = *netInt.Overrides.BridgeName + } switch netInt.Type { case types.NetworkInterface_MACVTAP: diff --git a/infrastructure/network/network_service.go b/infrastructure/network/network_service.go index 231a6183..b7de6d0a 100644 --- a/infrastructure/network/network_service.go +++ b/infrastructure/network/network_service.go @@ -17,16 +17,19 @@ import ( type Config struct { ParentDeviceName string + BridgeName string } func New(cfg *Config) ports.NetworkService { return &networkService{ parentDeviceName: cfg.ParentDeviceName, + bridgeName: cfg.BridgeName, } } type networkService struct { parentDeviceName string + bridgeName string } // IfaceCreate will create the network interface. @@ -47,14 +50,20 @@ func (n *networkService) IfaceCreate(ctx context.Context, input ports.IfaceCreat err error ) - if input.Type == models.IfaceTypeMacvtap { - if n.parentDeviceName == "" { - return nil, errors.ErrParentIfaceRequired + parentDeviceName := n.getParentIfaceName(input) + if parentDeviceName == "" { + if input.Type == models.IfaceTypeMacvtap { + return nil, errors.ErrParentIfaceRequiredForMacvtap + } + if input.Type == models.IfaceTypeTap && input.Attach { + return nil, errors.ErrParentIfaceRequiredForAttachingTap } + } - parentLink, err = netlink.LinkByName(n.parentDeviceName) + if parentDeviceName != "" { + parentLink, err = netlink.LinkByName(parentDeviceName) if err != nil { - return nil, fmt.Errorf("failed to lookup parent network interface %q: %w", n.parentDeviceName, err) + return nil, fmt.Errorf("failed to lookup parent network interface %q: %w", parentDeviceName, err) } } @@ -113,6 +122,14 @@ func (n *networkService) IfaceCreate(ctx context.Context, input ports.IfaceCreat logger.Debugf("created interface with mac %s", macIf.Attrs().HardwareAddr.String()) + if input.Type == models.IfaceTypeTap && input.Attach { + if err := netlink.LinkSetMaster(macIf, parentLink); err != nil { + return nil, fmt.Errorf("setting master for %s to %s: %w", macIf.Attrs().Name, parentLink.Attrs().Name, err) + } + + logger.Debugf("added interface %s to bridge %s", macIf.Attrs().Name, parentLink.Attrs().Name) + } + return &ports.IfaceDetails{ DeviceName: input.DeviceName, Type: input.Type, @@ -209,3 +226,15 @@ func (n *networkService) getIface(name string) (bool, netlink.Link, error) { return true, link, nil } + +func (n *networkService) getParentIfaceName(input ports.IfaceCreateInput) string { + if input.Type == models.IfaceTypeMacvtap { + return n.parentDeviceName + } + + if input.BridgeName != "" { + return input.BridgeName + } + + return n.bridgeName +} diff --git a/internal/command/flags/flags.go b/internal/command/flags/flags.go index e4c27c1c..5deaf597 100644 --- a/internal/command/flags/flags.go +++ b/internal/command/flags/flags.go @@ -12,6 +12,7 @@ const ( grpcEndpointFlag = "grpc-endpoint" httpEndpointFlag = "http-endpoint" parentIfaceFlag = "parent-iface" + bridgeNameFlag = "bridge-name" disableReconcileFlag = "disable-reconcile" disableAPIFlag = "disable-api" firecrackerBinFlag = "firecracker-bin" @@ -107,9 +108,11 @@ func AddNetworkFlagsToCommand(cmd *cobra.Command, cfg *config.Config) error { "", "The parent iface for the network interfaces. Note it could also be a bond") - if err := cmd.MarkFlagRequired(parentIfaceFlag); err != nil { - return fmt.Errorf("setting %s as required: %w", parentIfaceFlag, err) - } + cmd.Flags().StringVar( + &cfg.BridgeName, + bridgeNameFlag, + "", + "The name of the Linux bridge to attach tap devices to by default") return nil } diff --git a/internal/command/run/run.go b/internal/command/run/run.go index ff5752a6..2c0e7a0a 100644 --- a/internal/command/run/run.go +++ b/internal/command/run/run.go @@ -2,6 +2,7 @@ package run import ( "context" + "errors" "fmt" "net" "net/http" @@ -42,6 +43,10 @@ func NewCommand(cfg *config.Config) (*cobra.Command, error) { version.CommitHash, ) + if cfg.ParentIface == "" && cfg.BridgeName == "" { + return errors.New("You must supply at least one of parent interface, bridge name") + } + return nil }, RunE: func(c *cobra.Command, _ []string) error { diff --git a/internal/config/config.go b/internal/config/config.go index da9a0c97..a2c91f30 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -24,6 +24,8 @@ type Config struct { StateRootDir string // ParentIface is the name of the network interface to use for the parent in macvtap interfaces. ParentIface string + // BridgeName is the name of the Linux bridge to attach tap devices to be default. + BridgeName string // CtrSnapshotterKernel is the name of the containerd snapshotter to use for kernel images. CtrSnapshotterKernel string // CtrSocketPath is the path to the containerd socket. diff --git a/internal/inject/wire.go b/internal/inject/wire.go index 8d5761ca..01bace7c 100644 --- a/internal/inject/wire.go +++ b/internal/inject/wire.go @@ -76,6 +76,7 @@ func firecrackerConfig(cfg *config.Config) *firecracker.Config { func networkConfig(cfg *config.Config) *network.Config { return &network.Config{ ParentDeviceName: cfg.ParentIface, + BridgeName: cfg.BridgeName, } } diff --git a/internal/inject/wire_gen.go b/internal/inject/wire_gen.go index 00bb9da6..a6b69f8c 100644 --- a/internal/inject/wire_gen.go +++ b/internal/inject/wire_gen.go @@ -8,8 +8,6 @@ package inject import ( "fmt" - "time" - "github.com/spf13/afero" "github.com/weaveworks-liquidmetal/flintlock/core/application" "github.com/weaveworks-liquidmetal/flintlock/core/ports" @@ -21,6 +19,7 @@ import ( "github.com/weaveworks-liquidmetal/flintlock/infrastructure/ulid" "github.com/weaveworks-liquidmetal/flintlock/internal/config" "github.com/weaveworks-liquidmetal/flintlock/pkg/defaults" + "time" ) // Injectors from wire.go: @@ -91,6 +90,7 @@ func firecrackerConfig(cfg *config.Config) *firecracker.Config { func networkConfig(cfg *config.Config) *network.Config { return &network.Config{ ParentDeviceName: cfg.ParentIface, + BridgeName: cfg.BridgeName, } } diff --git a/userdocs/docs/grpc/types/proto.md b/userdocs/docs/grpc/types/proto.md index 9f5cfa2a..8c238ad8 100644 --- a/userdocs/docs/grpc/types/proto.md +++ b/userdocs/docs/grpc/types/proto.md @@ -18,6 +18,7 @@ - [Mount](#flintlock.types.Mount) - [NetworkInterface](#flintlock.types.NetworkInterface) - [NetworkInterfaceStatus](#flintlock.types.NetworkInterfaceStatus) + - [NetworkOverrides](#flintlock.types.NetworkOverrides) - [StaticAddress](#flintlock.types.StaticAddress) - [Volume](#flintlock.types.Volume) - [VolumeSource](#flintlock.types.VolumeSource) @@ -261,6 +262,7 @@ Mount represents a volume mount point. | type | [NetworkInterface.IfaceType](#flintlock.types.NetworkInterface.IfaceType) | | IfaceType specifies the type of network interface to create for use by the guest. | | guest_mac | [string](#string) | optional | GuestMAC allows the specifying of a specifi MAC address to use for the interface. If not supplied a autogenerated MAC address will be used. | | address | [StaticAddress](#flintlock.types.StaticAddress) | optional | Address is an optional static IP address to manually assign to this interface. If not supplied then DHCP will be used. | +| overrides | [NetworkOverrides](#flintlock.types.NetworkOverrides) | optional | Overrides is optional overrides applicable for network configuration. | @@ -284,6 +286,21 @@ Mount represents a volume mount point. + + +### NetworkOverrides +NetworkOverrides represents override values for a network interface. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| bridge_name | [string](#string) | optional | BridgeName is the name of the Linux bridge to attach TAP devices to. This overrides any value set at the overall flintlock level. | + + + + + + ### StaticAddress