diff --git a/go.mod b/go.mod index 2e8d8877e..00bee0c51 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/docker/go-events v0.0.0-20170721190031-9461782956ad // indirect github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 // indirect github.com/docker/go-units v0.3.3 - github.com/firecracker-microvm/firecracker-go-sdk v0.19.0 + github.com/firecracker-microvm/firecracker-go-sdk v0.19.1-0.20191114205152-9e2ff62839b2 github.com/go-ole/go-ole v1.2.4 // indirect github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384 // indirect github.com/gofrs/uuid v3.2.0+incompatible diff --git a/go.sum b/go.sum index a874fe880..7ee35c4a7 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 h1:X0fj836zx99zF github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/firecracker-microvm/firecracker-go-sdk v0.19.0 h1:Fgb3WhB4q3J5e+ksMBtjVwBTvbDtPAkx7eQulb2BOq8= -github.com/firecracker-microvm/firecracker-go-sdk v0.19.0/go.mod h1:kW0gxvPpPvMukUxxTO9DrpSlScrtrTDGY3VgjAj/Qwc= +github.com/firecracker-microvm/firecracker-go-sdk v0.19.1-0.20191114205152-9e2ff62839b2 h1:Ab52E0UlBOmMIAK/igRycsxSAJVDBDMYq+Wr/n7z2E0= +github.com/firecracker-microvm/firecracker-go-sdk v0.19.1-0.20191114205152-9e2ff62839b2/go.mod h1:kW0gxvPpPvMukUxxTO9DrpSlScrtrTDGY3VgjAj/Qwc= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvUbuvHW93esHg7F8N/OYeBBcJoTr0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= diff --git a/proto/firecracker.pb.go b/proto/firecracker.pb.go index b527e1dbf..6c0457384 100644 --- a/proto/firecracker.pb.go +++ b/proto/firecracker.pb.go @@ -463,6 +463,7 @@ func (m *GetVMMetadataResponse) GetMetadata() string { } type JailerConfig struct { + NetNS string `protobuf:"bytes,1,opt,name=NetNS,json=netNS,proto3" json:"NetNS,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -492,6 +493,13 @@ func (m *JailerConfig) XXX_DiscardUnknown() { var xxx_messageInfo_JailerConfig proto.InternalMessageInfo +func (m *JailerConfig) GetNetNS() string { + if m != nil { + return m.NetNS + } + return "" +} + func init() { proto.RegisterType((*CreateVMRequest)(nil), "CreateVMRequest") proto.RegisterType((*StopVMRequest)(nil), "StopVMRequest") @@ -507,38 +515,39 @@ func init() { func init() { proto.RegisterFile("firecracker.proto", fileDescriptor_a73317e9fb8da571) } var fileDescriptor_a73317e9fb8da571 = []byte{ - // 528 bytes of a gzipped FileDescriptorProto + // 541 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x6f, 0xd3, 0x4e, - 0x10, 0x95, 0x7f, 0x4d, 0xda, 0x78, 0xdc, 0xa6, 0xbf, 0xac, 0x5a, 0x58, 0x55, 0x15, 0xb2, 0x7c, - 0xa8, 0x2c, 0x0e, 0x95, 0x68, 0x2e, 0x88, 0x13, 0x21, 0x21, 0x95, 0x5b, 0x8c, 0xd0, 0xa6, 0xe4, - 0xc0, 0x6d, 0x71, 0xc6, 0xa9, 0xb1, 0xb3, 0x1b, 0x76, 0x37, 0xa5, 0x9c, 0xf9, 0x44, 0x7c, 0x43, - 0xe4, 0xcd, 0x3f, 0x27, 0x82, 0x08, 0x89, 0x93, 0x77, 0xdf, 0xbc, 0x99, 0xf7, 0x34, 0x7e, 0x36, - 0xb4, 0xd2, 0x4c, 0x61, 0xa2, 0x78, 0x92, 0xa3, 0xba, 0x9c, 0x2a, 0x69, 0xe4, 0x99, 0x67, 0xbe, - 0x4f, 0x51, 0xcf, 0x2f, 0xc1, 0x8f, 0x1a, 0x1c, 0x77, 0x15, 0x72, 0x83, 0xc3, 0x98, 0xe1, 0xd7, - 0x19, 0x6a, 0x43, 0x08, 0xd4, 0x86, 0x71, 0xd4, 0xa3, 0x8e, 0xef, 0x84, 0x2e, 0xab, 0x3d, 0xc4, - 0x51, 0x8f, 0xbc, 0x06, 0x88, 0x79, 0x72, 0x9f, 0x09, 0xec, 0xa6, 0x63, 0xfa, 0x9f, 0xef, 0x84, - 0xde, 0x95, 0x7f, 0xd9, 0x5f, 0x0f, 0x5f, 0x56, 0xa5, 0x48, 0xb3, 0xf1, 0x4c, 0x71, 0x93, 0x49, - 0xc1, 0x60, 0xb2, 0xea, 0x21, 0x21, 0x1c, 0xdf, 0xa2, 0x12, 0x58, 0x44, 0x13, 0x3e, 0xc6, 0x0f, - 0xdc, 0xdc, 0xd3, 0x3d, 0x2b, 0x70, 0x9c, 0x6f, 0xc2, 0xe4, 0x19, 0xc0, 0x9c, 0xd9, 0x51, 0x63, - 0x4d, 0x6b, 0x96, 0x04, 0xf9, 0x0a, 0x21, 0x6d, 0x70, 0x99, 0x94, 0xa6, 0xa7, 0xb2, 0x07, 0xa4, - 0x75, 0x6b, 0xe5, 0xb4, 0x6a, 0x65, 0x55, 0x64, 0xae, 0x5a, 0x1e, 0xc9, 0x4b, 0xf0, 0xec, 0x21, - 0x96, 0x33, 0x61, 0x34, 0xdd, 0xf7, 0xf7, 0x42, 0xef, 0xea, 0x49, 0xb5, 0x6d, 0x5d, 0x66, 0xde, - 0x68, 0x4d, 0x25, 0x37, 0xd0, 0x7a, 0x8f, 0xe6, 0x9b, 0x54, 0x79, 0x24, 0x0c, 0xaa, 0x94, 0x27, - 0xa8, 0xe9, 0x81, 0xed, 0x3f, 0xaf, 0xf6, 0x6f, 0x93, 0x58, 0x4b, 0x6c, 0xb7, 0x91, 0x0b, 0x68, - 0x76, 0xa5, 0x30, 0x3c, 0x13, 0xa8, 0xba, 0xe5, 0x78, 0xda, 0xf0, 0x9d, 0xb0, 0xce, 0x9a, 0xc9, - 0x06, 0x4a, 0x5e, 0x01, 0x7d, 0xfb, 0x98, 0x99, 0x4e, 0x6a, 0x50, 0x75, 0x8a, 0xe2, 0x8e, 0xeb, - 0x5c, 0xf7, 0xb0, 0x40, 0x83, 0x23, 0xea, 0xfa, 0x4e, 0xd8, 0x60, 0x14, 0xff, 0x50, 0x27, 0x2f, - 0xe0, 0xf0, 0x86, 0x67, 0x45, 0x39, 0xaa, 0x7c, 0x17, 0x14, 0xec, 0x86, 0x8e, 0x2e, 0xab, 0x20, - 0x3b, 0xfc, 0x52, 0xb9, 0x05, 0xb7, 0x70, 0x34, 0x30, 0x72, 0xba, 0x3b, 0x02, 0x17, 0xd0, 0xbc, - 0xcb, 0x26, 0x28, 0x67, 0x66, 0x80, 0x89, 0x14, 0x23, 0x6d, 0x63, 0x70, 0xc4, 0x9a, 0x66, 0x03, - 0x0d, 0x2e, 0xe0, 0xff, 0x6b, 0x34, 0xc3, 0x38, 0x12, 0xa9, 0xdc, 0x31, 0x2f, 0xf8, 0xe9, 0x40, - 0xab, 0x42, 0xd4, 0x53, 0x29, 0x34, 0xfe, 0x56, 0xf9, 0x1c, 0xdc, 0x72, 0x6b, 0xf8, 0x68, 0xa2, - 0xde, 0x42, 0xd4, 0x4d, 0x96, 0x40, 0x19, 0x97, 0x81, 0x4c, 0x72, 0x34, 0x95, 0x4c, 0x81, 0x5e, - 0x21, 0xc4, 0x07, 0xef, 0x9d, 0x1c, 0xf7, 0xb3, 0x54, 0x5a, 0xc2, 0x3c, 0x4f, 0x5e, 0xb1, 0x86, - 0xca, 0x68, 0xc6, 0x68, 0x54, 0x96, 0xe8, 0x15, 0xab, 0x3e, 0x8f, 0xe6, 0x64, 0x13, 0x0e, 0xfa, - 0x70, 0x32, 0x28, 0x2d, 0xc7, 0x68, 0xf8, 0x88, 0x1b, 0xbe, 0x6b, 0x5f, 0x67, 0xd0, 0x58, 0xd2, - 0xac, 0x69, 0x97, 0x35, 0x26, 0x8b, 0x7b, 0x10, 0xc1, 0xd3, 0x8f, 0xd3, 0x91, 0xfd, 0xea, 0xfe, - 0x75, 0xd4, 0x73, 0x38, 0xb9, 0xfe, 0x4b, 0x4b, 0x41, 0x1b, 0x4e, 0xb7, 0xb8, 0x8b, 0xad, 0x57, - 0x05, 0x9c, 0x2d, 0x81, 0xe6, 0x66, 0x9e, 0xde, 0x1c, 0x7c, 0xaa, 0xdb, 0x7f, 0xc7, 0xe7, 0x7d, - 0xfb, 0x68, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x04, 0x79, 0x66, 0xac, 0x64, 0x04, 0x00, 0x00, + 0x10, 0x95, 0x7f, 0x4d, 0xda, 0x78, 0xdc, 0xa6, 0xbf, 0xac, 0x5a, 0x58, 0x55, 0x15, 0xb2, 0x2c, + 0x54, 0x45, 0x1c, 0x2a, 0xd1, 0x5e, 0x10, 0x27, 0x4a, 0x42, 0x2b, 0xb7, 0xb8, 0x42, 0x9b, 0xd2, + 0x03, 0xb7, 0xc5, 0x19, 0xa7, 0x26, 0xce, 0x6e, 0xd8, 0x9d, 0x94, 0x72, 0xe6, 0x13, 0xf1, 0x0d, + 0x91, 0x37, 0xff, 0x9c, 0x08, 0x2a, 0x24, 0x4e, 0x9e, 0x79, 0xf3, 0x66, 0xe6, 0x69, 0xfc, 0x6c, + 0x68, 0x65, 0xb9, 0xc1, 0xd4, 0xc8, 0x74, 0x88, 0xe6, 0x78, 0x6c, 0x34, 0xe9, 0x83, 0x80, 0xbe, + 0x8f, 0xd1, 0x4e, 0x93, 0xe8, 0x47, 0x0d, 0x76, 0x3b, 0x06, 0x25, 0xe1, 0x6d, 0x22, 0xf0, 0xeb, + 0x04, 0x2d, 0x31, 0x06, 0xb5, 0xdb, 0x24, 0xee, 0x72, 0x2f, 0xf4, 0xda, 0xbe, 0xa8, 0xdd, 0x27, + 0x71, 0x97, 0xbd, 0x01, 0x48, 0x64, 0x7a, 0x97, 0x2b, 0xec, 0x64, 0x03, 0xfe, 0x5f, 0xe8, 0xb5, + 0x83, 0x93, 0xf0, 0xf8, 0x7c, 0x39, 0x7c, 0x5e, 0xd5, 0x2a, 0xcb, 0x07, 0x13, 0x23, 0x29, 0xd7, + 0x4a, 0xc0, 0x68, 0xd1, 0xc3, 0xda, 0xb0, 0x7b, 0x85, 0x46, 0x61, 0x11, 0x8f, 0xe4, 0x00, 0x3f, + 0x48, 0xba, 0xe3, 0x1b, 0x6e, 0xc1, 0xee, 0x70, 0x15, 0x66, 0xcf, 0x00, 0xa6, 0xcc, 0x33, 0x33, + 0xb0, 0xbc, 0xe6, 0x48, 0x30, 0x5c, 0x20, 0xec, 0x14, 0x7c, 0xa1, 0x35, 0x75, 0x4d, 0x7e, 0x8f, + 0xbc, 0xee, 0xa4, 0xec, 0x57, 0xa5, 0x2c, 0x8a, 0xc2, 0x37, 0xf3, 0x90, 0xbd, 0x82, 0xc0, 0x05, + 0x89, 0x9e, 0x28, 0xb2, 0x7c, 0x33, 0xdc, 0x68, 0x07, 0x27, 0x4f, 0xaa, 0x6d, 0xcb, 0xb2, 0x08, + 0xfa, 0x4b, 0x2a, 0xbb, 0x84, 0xd6, 0x35, 0xd2, 0x37, 0x6d, 0x86, 0xb1, 0x22, 0x34, 0x99, 0x4c, + 0xd1, 0xf2, 0x2d, 0xd7, 0x7f, 0x58, 0xed, 0x5f, 0x27, 0x89, 0x96, 0x5a, 0x6f, 0x63, 0x47, 0xd0, + 0xec, 0x68, 0x45, 0x32, 0x57, 0x68, 0x3a, 0xe5, 0x78, 0xde, 0x08, 0xbd, 0x76, 0x5d, 0x34, 0xd3, + 0x15, 0x94, 0xbd, 0x06, 0xfe, 0xee, 0x21, 0xa7, 0xb3, 0x8c, 0xd0, 0x9c, 0x15, 0xc5, 0x8d, 0xb4, + 0x43, 0xdb, 0xc5, 0x02, 0x09, 0xfb, 0xdc, 0x0f, 0xbd, 0x76, 0x43, 0x70, 0xfc, 0x43, 0x9d, 0xbd, + 0x84, 0xed, 0x4b, 0x99, 0x17, 0xe5, 0xa8, 0xf2, 0x5d, 0x70, 0x70, 0x17, 0xda, 0x39, 0xae, 0x82, + 0x62, 0xfb, 0x4b, 0x25, 0x8b, 0xae, 0x60, 0xa7, 0x47, 0x7a, 0xfc, 0xb8, 0x05, 0x8e, 0xa0, 0x79, + 0x93, 0x8f, 0x50, 0x4f, 0xa8, 0x87, 0xa9, 0x56, 0x7d, 0xeb, 0x6c, 0xb0, 0x23, 0x9a, 0xb4, 0x82, + 0x46, 0x47, 0xf0, 0xff, 0x05, 0xd2, 0x6d, 0x12, 0xab, 0x4c, 0x3f, 0x32, 0x2f, 0xfa, 0xe9, 0x41, + 0xab, 0x42, 0xb4, 0x63, 0xad, 0x2c, 0xfe, 0x76, 0xf3, 0x21, 0xf8, 0xe5, 0xd5, 0xf0, 0x81, 0xe2, + 0xee, 0x6c, 0xa9, 0x9f, 0xce, 0x81, 0xd2, 0x2e, 0x3d, 0x9d, 0x0e, 0x91, 0x2a, 0x9e, 0x02, 0xbb, + 0x40, 0x58, 0x08, 0xc1, 0x7b, 0x3d, 0x38, 0xcf, 0x33, 0xed, 0x08, 0x53, 0x3f, 0x05, 0xc5, 0x12, + 0x2a, 0xad, 0x99, 0x20, 0x99, 0x3c, 0xb5, 0x0b, 0x56, 0x7d, 0x6a, 0xcd, 0xd1, 0x2a, 0x1c, 0x9d, + 0xc3, 0x5e, 0xaf, 0x94, 0x9c, 0x20, 0xc9, 0xbe, 0x24, 0xf9, 0xd8, 0xbd, 0x0e, 0xa0, 0x31, 0xa7, + 0x39, 0xd1, 0xbe, 0x68, 0x8c, 0x66, 0x79, 0x14, 0xc3, 0xd3, 0x8f, 0xe3, 0xbe, 0xfb, 0xea, 0xfe, + 0x75, 0xd4, 0x0b, 0xd8, 0xbb, 0xf8, 0x4b, 0x49, 0xd1, 0x29, 0xec, 0xaf, 0x71, 0x67, 0x57, 0xaf, + 0x2e, 0xf0, 0xd6, 0x16, 0x3c, 0x5f, 0xf5, 0x13, 0xdb, 0x83, 0xfa, 0x35, 0xd2, 0x75, 0x6f, 0x46, + 0xac, 0xab, 0x32, 0x79, 0xbb, 0xf5, 0xa9, 0xee, 0xfe, 0x28, 0x9f, 0x37, 0xdd, 0xe3, 0xf4, 0x57, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x16, 0x31, 0x73, 0x7a, 0x04, 0x00, 0x00, } diff --git a/proto/firecracker.proto b/proto/firecracker.proto index 239ed2dc6..9be1e22cc 100644 --- a/proto/firecracker.proto +++ b/proto/firecracker.proto @@ -72,5 +72,6 @@ message GetVMMetadataResponse { } message JailerConfig { + string NetNS = 1; } diff --git a/runtime/cni_integ_test.go b/runtime/cni_integ_test.go index e7e62cb60..002988996 100644 --- a/runtime/cni_integ_test.go +++ b/runtime/cni_integ_test.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/ttrpcutil" + "github.com/firecracker-microvm/firecracker-go-sdk/cni/cmd/tc-redirect-tap/args" "github.com/shirou/gopsutil/cpu" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -39,8 +40,7 @@ import ( ) func TestCNISupport_Isolated(t *testing.T) { - prepareIntegTest(t) - + prepareIntegTest(t, withJailer()) testTimeout := 120 * time.Second ctx, cancel := context.WithTimeout(namespaces.WithNamespace(context.Background(), defaultNamespace), testTimeout) defer cancel() @@ -96,8 +96,23 @@ func TestCNISupport_Isolated(t *testing.T) { CNIConfig: &proto.CNIConfiguration{ NetworkName: cniNetworkName, InterfaceName: "veth0", + Args: []*proto.CNIConfiguration_CNIArg{ + { + Key: "IgnoreUnknown", + Value: "true", + }, + { + Key: args.TCRedirectTapUID, + Value: fmt.Sprintf("%d", jailerUID), + }, + { + Key: args.TCRedirectTapGID, + Value: fmt.Sprintf("%d", jailerGID), + }, + }, }, }}, + JailerConfig: &proto.JailerConfig{}, }) require.NoError(t, err, "failed to create vm") diff --git a/runtime/runc_jailer.go b/runtime/runc_jailer.go index bec617c65..1f1207da3 100644 --- a/runtime/runc_jailer.go +++ b/runtime/runc_jailer.go @@ -35,6 +35,10 @@ import ( "github.com/firecracker-microvm/firecracker-containerd/internal/vm" ) +const ( + networkNamespaceRuncName = "network" +) + // runcJailer uses runc to set up a jailed environment for the Firecracker VM. type runcJailer struct { ctx context.Context @@ -46,6 +50,7 @@ type runcJailer struct { runcBinaryPath string uid uint32 gid uint32 + configSpec specs.Spec } const firecrackerFileName = "firecracker" @@ -63,6 +68,19 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, ociBundlePath, run gid: gid, } + spec := specs.Spec{} + var configBytes []byte + configBytes, err := ioutil.ReadFile(runcConfigPath) + if err != nil { + return nil, errors.Wrapf(err, "failed to read %s", runcConfigPath) + } + + if err = json.Unmarshal(configBytes, &spec); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal %s", runcConfigPath) + } + + j.configSpec = spec + rootPath := j.RootPath() const mode = os.FileMode(0700) @@ -77,17 +95,17 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, ociBundlePath, run // JailPath returns the base directory from where the jail binary will be ran // from -func (j runcJailer) OCIBundlePath() string { +func (j *runcJailer) OCIBundlePath() string { return j.ociBundlePath } // RootPath returns the root fs of the jailed system. -func (j runcJailer) RootPath() string { +func (j *runcJailer) RootPath() string { return filepath.Join(j.OCIBundlePath(), rootfsFolder) } // JailPath will return the OCI bundle rootfs path -func (j runcJailer) JailPath() vm.Dir { +func (j *runcJailer) JailPath() vm.Dir { return vm.Dir(j.RootPath()) } @@ -95,11 +113,17 @@ func (j runcJailer) JailPath() vm.Dir { // instance. In addition, some configuration values will be overwritten to the // jailed values, like SocketPath in the machineConfig. func (j *runcJailer) BuildJailedMachine(cfg *Config, machineConfig *firecracker.Config, vmID string) ([]firecracker.Opt, error) { - handler := j.BuildJailedRootHandler(cfg, &machineConfig.SocketPath, vmID) + handler := j.BuildJailedRootHandler(cfg, machineConfig, vmID) fifoHandler := j.BuildLinkFifoHandler() // Build a new client since BuildJailedRootHandler modifies the socket path value. client := firecracker.NewClient(machineConfig.SocketPath, j.logger, machineConfig.Debug) + if machineConfig.NetNS == "" { + if netns := getNetNS(j.configSpec); netns != "" { + machineConfig.NetNS = netns + } + } + opts := []firecracker.Opt{ firecracker.WithProcessRunner(j.jailerCommand(vmID, cfg.Debug)), firecracker.WithClient(client), @@ -120,10 +144,10 @@ func (j *runcJailer) BuildJailedMachine(cfg *Config, machineConfig *firecracker. // BuildJailedRootHandler will populate the jail with the necessary files, which may be // device nodes, hard links, and/or bind-mount targets -func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmID string) firecracker.Handler { +func (j *runcJailer) BuildJailedRootHandler(cfg *Config, machineConfig *firecracker.Config, vmID string) firecracker.Handler { ociBundlePath := j.OCIBundlePath() rootPath := j.RootPath() - *socketPath = filepath.Join(rootPath, "api.socket") + machineConfig.SocketPath = filepath.Join(rootPath, "api.socket") return firecracker.Handler{ Name: jailerHandlerName, @@ -136,7 +160,9 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmI } j.logger.Debug("Overwritting process args of config") - if err := j.overwriteConfig(cfg, filepath.Base(m.Cfg.SocketPath), rootPathToConfig); err != nil { + // we pass m.Cfg as opposed to machineConfig as we want the populated + // config defaults when calling NewMachine + if err := j.overwriteConfig(cfg, &m.Cfg, filepath.Base(m.Cfg.SocketPath), rootPathToConfig); err != nil { return errors.Wrap(err, "failed to overwrite config.json") } @@ -206,7 +232,7 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmI // BuildLinkFifoHandler will return a new firecracker.Handler with the function // that will allow linking of the fifos making them visible to Firecracker. -func (j runcJailer) BuildLinkFifoHandler() firecracker.Handler { +func (j *runcJailer) BuildLinkFifoHandler() firecracker.Handler { return firecracker.Handler{ Name: jailerFifoHandlerName, Fn: func(ctx context.Context, m *firecracker.Machine) error { @@ -232,7 +258,7 @@ func (j runcJailer) BuildLinkFifoHandler() firecracker.Handler { // StubDrivesOptions will return a set of options used to create a new stub // drive handler. -func (j runcJailer) StubDrivesOptions() []stubDrivesOpt { +func (j *runcJailer) StubDrivesOptions() []stubDrivesOpt { return []stubDrivesOpt{ func(drives []models.Drive) error { for _, drive := range drives { @@ -251,7 +277,7 @@ func (j runcJailer) StubDrivesOptions() []stubDrivesOpt { // the jail. For block devices we will use mknod to create the device and then // set the correct permissions to ensure visibility in the jail. Regular files // will be copied into the jail. -func (j runcJailer) ExposeFileToJail(srcPath string) error { +func (j *runcJailer) ExposeFileToJail(srcPath string) error { uid := j.uid gid := j.gid @@ -292,7 +318,7 @@ func (j runcJailer) ExposeFileToJail(srcPath string) error { } // copyFileToJail will copy a file from src to dst, and chown the new file to the jail user. -func (j runcJailer) copyFileToJail(src, dst string, mode os.FileMode) error { +func (j *runcJailer) copyFileToJail(src, dst string, mode os.FileMode) error { if err := copyFile(src, dst, mode); err != nil { return err } @@ -340,7 +366,7 @@ func copyFile(src, dst string, mode os.FileMode) error { return nil } -func (j runcJailer) jailerCommand(containerName string, isDebug bool) *exec.Cmd { +func (j *runcJailer) jailerCommand(containerName string, isDebug bool) *exec.Cmd { cmd := exec.CommandContext(j.ctx, j.runcBinaryPath, "run", containerName) cmd.Dir = j.OCIBundlePath() @@ -353,19 +379,8 @@ func (j runcJailer) jailerCommand(containerName string, isDebug bool) *exec.Cmd } // overwriteConfig will set the proper default values if a field had not been set. -// -// TODO: Add netns -func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string) error { - spec := specs.Spec{} - configBytes, err := ioutil.ReadFile(configPath) - if err != nil { - return err - } - - if err := json.Unmarshal(configBytes, &spec); err != nil { - return err - } - +func (j *runcJailer) overwriteConfig(cfg *Config, machineConfig *firecracker.Config, socketPath, configPath string) error { + spec := j.configSpec if spec.Process.User.UID != 0 || spec.Process.User.GID != 0 { return fmt.Errorf( @@ -376,13 +391,22 @@ func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string) } spec = j.setDefaultConfigValues(cfg, socketPath, spec) - spec.Root.Path = rootfsFolder spec.Root.Readonly = false spec.Process.User.UID = j.uid spec.Process.User.GID = j.gid - configBytes, err = json.Marshal(&spec) + if machineConfig.NetNS != "" { + for i, ns := range spec.Linux.Namespaces { + if ns.Type == networkNamespaceRuncName { + ns.Path = machineConfig.NetNS + spec.Linux.Namespaces[i] = ns + break + } + } + } + + configBytes, err := json.Marshal(&spec) if err != nil { return err } @@ -396,7 +420,7 @@ func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string) // setDefaultConfigValues will process the spec file provided and allow any // empty/zero values to be replaced with default values. -func (j runcJailer) setDefaultConfigValues(cfg *Config, socketPath string, spec specs.Spec) specs.Spec { +func (j *runcJailer) setDefaultConfigValues(cfg *Config, socketPath string, spec specs.Spec) specs.Spec { if spec.Process == nil { spec.Process = &specs.Process{} } @@ -448,3 +472,13 @@ func mkdirAllWithPermissions(path string, mode os.FileMode, uid, gid uint32) err return nil } + +func getNetNS(spec specs.Spec) string { + for _, ns := range spec.Linux.Namespaces { + if ns.Type == networkNamespaceRuncName { + return ns.Path + } + } + + return "" +} diff --git a/runtime/runc_jailer_test.go b/runtime/runc_jailer_test.go index 52ad7fc93..bb7d085b4 100644 --- a/runtime/runc_jailer_test.go +++ b/runtime/runc_jailer_test.go @@ -61,22 +61,22 @@ func TestBuildJailedRootHandler_Isolated(t *testing.T) { KernelImagePath: kernelImagePath, RootDrive: rootDrivePath, } - socketPath := "/path/to/api.socket" + machineConfig := firecracker.Config{ + SocketPath: "/path/to/api.socket", + KernelImagePath: kernelImagePath, + Drives: []models.Drive{ + { + PathOnHost: firecracker.String(rootDrivePath), + IsRootDevice: firecracker.Bool(true), + IsReadOnly: firecracker.Bool(true), + }, + }, + } vmID := "foo" - handler := jailer.BuildJailedRootHandler(&cfg, &socketPath, vmID) + handler := jailer.BuildJailedRootHandler(&cfg, &machineConfig, vmID) machine := firecracker.Machine{ - Cfg: firecracker.Config{ - SocketPath: socketPath, - KernelImagePath: kernelImagePath, - Drives: []models.Drive{ - { - PathOnHost: firecracker.String(rootDrivePath), - IsRootDevice: firecracker.Bool(true), - IsReadOnly: firecracker.Bool(true), - }, - }, - }, + Cfg: machineConfig, } err = handler.Fn(context.Background(), &machine) assert.NoError(t, err, "jailed handler failed to run") diff --git a/runtime/service.go b/runtime/service.go index f10722473..4d4ebe527 100644 --- a/runtime/service.go +++ b/runtime/service.go @@ -698,6 +698,10 @@ func (s *service) buildVMConfiguration(req *proto.CreateVMRequest) (*firecracker VMID: s.vmID, } + if req.JailerConfig != nil { + cfg.NetNS = req.JailerConfig.NetNS + } + s.logger.Debugf("using socket path: %s", cfg.SocketPath) // Kernel configuration diff --git a/runtime/service_integ_test.go b/runtime/service_integ_test.go index ff730d338..423d7c098 100644 --- a/runtime/service_integ_test.go +++ b/runtime/service_integ_test.go @@ -37,6 +37,7 @@ import ( "github.com/containerd/containerd/pkg/ttrpcutil" "github.com/containerd/containerd/runtime" "github.com/containerd/typeurl" + "github.com/containernetworking/plugins/pkg/ns" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/shirou/gopsutil/process" @@ -214,6 +215,8 @@ func createTapDevice(ctx context.Context, tapName string) error { func TestMultipleVMs_Isolated(t *testing.T) { prepareIntegTest(t, withJailer()) + netns, err := ns.GetCurrentNS() + cases := []struct { MaxContainers int32 JailerConfig *proto.JailerConfig @@ -229,11 +232,15 @@ func TestMultipleVMs_Isolated(t *testing.T) { }, { MaxContainers: 3, - JailerConfig: &proto.JailerConfig{}, + JailerConfig: &proto.JailerConfig{ + NetNS: netns.Path(), + }, }, { MaxContainers: 3, - JailerConfig: &proto.JailerConfig{}, + JailerConfig: &proto.JailerConfig{ + NetNS: netns.Path(), + }, }, } @@ -262,6 +269,7 @@ func TestMultipleVMs_Isolated(t *testing.T) { tapName := fmt.Sprintf("tap%d", vmID) err = createTapDevice(ctx, tapName) + require.NoError(t, err, "failed to create tap device for vm %d", vmID) rootfsPath := defaultVMRootfsPath @@ -288,10 +296,6 @@ func TestMultipleVMs_Isolated(t *testing.T) { JailerConfig: jailerConfig, } - if jailerConfig != nil { - req.NetworkInterfaces = nil - } - _, err = fcClient.CreateVM(ctx, req) require.NoError(t, err, "failed to create vm") @@ -308,13 +312,6 @@ func TestMultipleVMs_Isolated(t *testing.T) { fmt.Sprintf("/bin/sleep %d", testTimeout/time.Second), }, " && ")) - if jailerConfig != nil { - // TODO: this if statement block can go away once we add netns - processArgs = oci.WithProcessArgs("/bin/sh", "-c", strings.Join([]string{ - fmt.Sprintf("/bin/sleep %d", testTimeout/time.Second), - }, " && ")) - } - // spawn a container that just prints the VM's eth0 mac address (which we have set uniquely per VM) newContainer, err := client.NewContainer(ctx, containerName, @@ -443,20 +440,13 @@ func TestMultipleVMs_Isolated(t *testing.T) { stdoutLines := strings.Split(strings.TrimSpace(taskStdout.String()), "\n") lines := 2 - if jailerConfig != nil { - lines = 1 - } require.Len(t, stdoutLines, lines) printedVMID := strings.TrimSpace(stdoutLines[0]) - // TODO: Remove this if statement once we can add a netns which - // will allow firecracker to have visibility of the tap devices. - if jailerConfig == nil { - require.Equal(t, vmIDtoMacAddr(uint(vmID)), printedVMID, "unexpected VMID output from container %q", containerName) + require.Equal(t, vmIDtoMacAddr(uint(vmID)), printedVMID, "unexpected VMID output from container %q", containerName) - taskMntNS := strings.TrimSpace(stdoutLines[1]) - require.Equal(t, execMntNS, taskMntNS, "unexpected mnt NS output from container %q", containerName) - } + taskMntNS := strings.TrimSpace(stdoutLines[1]) + require.Equal(t, execMntNS, taskMntNS, "unexpected mnt NS output from container %q", containerName) case <-ctx.Done(): require.Fail(t, "context cancelled",