diff --git a/api/grpc/nvidia/ipam/node/v1/node.pb.go b/api/grpc/nvidia/ipam/node/v1/node.pb.go index aa626ef..61f5466 100644 --- a/api/grpc/nvidia/ipam/node/v1/node.pb.go +++ b/api/grpc/nvidia/ipam/node/v1/node.pb.go @@ -318,6 +318,8 @@ type IPAMFeatures struct { // optional, request IP of the default gateway from the pool be allocated for container AllocateDefaultGateway bool `protobuf:"varint,1,opt,name=allocate_default_gateway,json=allocateDefaultGateway,proto3" json:"allocate_default_gateway,omitempty"` + // optional, request IP with the given index in the chunk allocated for the particular node to be allocated for the container + AllocateIpWithIndex *int32 `protobuf:"varint,2,opt,name=allocate_ip_with_index,json=allocateIpWithIndex,proto3,oneof" json:"allocate_ip_with_index,omitempty"` } func (x *IPAMFeatures) Reset() { @@ -359,6 +361,13 @@ func (x *IPAMFeatures) GetAllocateDefaultGateway() bool { return false } +func (x *IPAMFeatures) GetAllocateIpWithIndex() int32 { + if x != nil && x.AllocateIpWithIndex != nil { + return *x.AllocateIpWithIndex + } + return 0 +} + // IsAllocatedRequest contains parameters for IsAllocated rpc call type IsAllocatedRequest struct { state protoimpl.MessageState @@ -759,70 +768,76 @@ var file_nvidia_ipam_node_v1_node_proto_rawDesc = []byte{ 0x6b, 0x38, 0x73, 0x5f, 0x70, 0x6f, 0x64, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x38, 0x73, 0x50, 0x6f, 0x64, 0x55, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x0c, 0x49, 0x50, 0x41, - 0x4d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x6c, 0x6c, - 0x6f, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x67, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x61, 0x6c, 0x6c, - 0x6f, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x22, 0x59, 0x0a, 0x12, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x61, 0x72, + 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x0c, 0x49, 0x50, + 0x41, 0x4d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x61, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x61, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x12, 0x38, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, + 0x5f, 0x69, 0x70, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, + 0x49, 0x70, 0x57, 0x69, 0x74, 0x68, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x42, 0x19, + 0x0a, 0x17, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x5f, 0x77, + 0x69, 0x74, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x59, 0x0a, 0x12, 0x49, 0x73, 0x41, + 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x43, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, + 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x50, 0x41, 0x4d, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x22, 0x58, 0x0a, 0x11, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x50, 0x41, 0x4d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x58, - 0x0a, 0x11, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, - 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x50, - 0x41, 0x4d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x59, 0x0a, 0x10, 0x41, 0x6c, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0b, - 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, - 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, - 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x32, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, - 0x74, 0x22, 0x15, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x61, 0x6c, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x53, - 0x0a, 0x08, 0x50, 0x6f, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x4f, - 0x4f, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x49, 0x50, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x50, - 0x4f, 0x4f, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x49, 0x44, 0x52, 0x50, 0x4f, 0x4f, - 0x4c, 0x10, 0x02, 0x32, 0xad, 0x02, 0x0a, 0x0b, 0x49, 0x50, 0x41, 0x4d, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x12, - 0x24, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, - 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, - 0x0a, 0x0b, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x27, 0x2e, + 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x59, + 0x0a, 0x10, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, + 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x61, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x0e, 0x41, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, + 0x12, 0x18, 0x0a, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6f, + 0x6f, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, - 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x41, - 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, - 0x12, 0x26, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, - 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x70, 0x6f, + 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, + 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x05, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x6c, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, + 0x0a, 0x12, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x53, 0x0a, 0x08, 0x50, 0x6f, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x19, 0x0a, 0x15, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x50, + 0x4f, 0x4f, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x50, 0x50, 0x4f, 0x4f, 0x4c, 0x10, + 0x01, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x4f, 0x4f, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, + 0x49, 0x44, 0x52, 0x50, 0x4f, 0x4f, 0x4c, 0x10, 0x02, 0x32, 0xad, 0x02, 0x0a, 0x0b, 0x49, 0x50, + 0x41, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x08, 0x41, 0x6c, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, + 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6e, 0x76, + 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x0b, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x12, 0x27, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, + 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6e, + 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x6c, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, + 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, + 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x6d, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -1015,6 +1030,7 @@ func file_nvidia_ipam_node_v1_node_proto_init() { } } } + file_nvidia_ipam_node_v1_node_proto_msgTypes[3].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/api/grpc/proto/nvidia/ipam/node/v1/node.proto b/api/grpc/proto/nvidia/ipam/node/v1/node.proto index e6229ee..565c29d 100644 --- a/api/grpc/proto/nvidia/ipam/node/v1/node.proto +++ b/api/grpc/proto/nvidia/ipam/node/v1/node.proto @@ -95,6 +95,8 @@ message IPAMMetadata { message IPAMFeatures { // optional, request IP of the default gateway from the pool be allocated for container bool allocate_default_gateway = 1; + // optional, request IP with the given index in the chunk allocated for the particular node to be allocated for the container + optional int32 allocate_ip_with_index = 2; } // IsAllocatedRequest contains parameters for IsAllocated rpc call diff --git a/docs/extra-cni-args.md b/docs/extra-cni-args.md index 4669f99..bceac3b 100644 --- a/docs/extra-cni-args.md +++ b/docs/extra-cni-args.md @@ -4,12 +4,13 @@ The NV-IPAM plugin supports the following [args in network config](https://www.cni.dev/docs/conventions/#args-in-network-config): -| Argument | Type | Description | -|------------------------|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| ips | `[]string` | Request static IPs from the pool | -| poolNames | `[]string,` max len is 2 | Name of the pools to be used for IP allocation. _The field has higher priority than `ipam.poolName` | -| poolType | `string` | Type (`ippool`, `cidrpool`) of the pool which is referred by the `poolNames`. _The field has higher priority than_ `ipam.poolType` | -| allocateDefaultGateway | `bool` | Request to allocate pool's default gateway as interface IP address for the container. Pool must have the gateway when this argument is used. The argument can't be used together with static IP request. | +| Argument | Type | Description | +|------------------------|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ips | `[]string` | Request static IPs from the pool | +| poolNames | `[]string,` max len is 2 | Name of the pools to be used for IP allocation. _The field has higher priority than `ipam.poolName` | +| poolType | `string` | Type (`ippool`, `cidrpool`) of the pool which is referred by the `poolNames`. _The field has higher priority than_ `ipam.poolType` | +| allocateDefaultGateway | `bool` | Request to allocate pool's default gateway as interface IP address for the container. Pool must have the gateway when this argument is used. The argument can't be used together with static IP request or with allocating IP of specific index. | +| allocateIPWithIndex | `int` | Request to allocate pool's IP with the given index as interface IP address for the container. The argument can't be used together with static IP request or with allocating the gateway IP. | diff --git a/pkg/cni/plugin/plugin.go b/pkg/cni/plugin/plugin.go index c8b9f99..056510c 100644 --- a/pkg/cni/plugin/plugin.go +++ b/pkg/cni/plugin/plugin.go @@ -224,6 +224,7 @@ func cniConfToGRPCReq(conf *types.NetConf, args *skel.CmdArgs) *nodev1.IPAMParam RequestedIps: requestedIPs, Features: &nodev1.IPAMFeatures{ AllocateDefaultGateway: conf.IPAM.Features.AllocateDefaultGateway, + AllocateIpWithIndex: conf.IPAM.Features.AllocateIPWithIndex, }, } if req.Metadata.K8SPodUid == "" { diff --git a/pkg/cni/types/types.go b/pkg/cni/types/types.go index 6e900ab..9f67171 100644 --- a/pkg/cni/types/types.go +++ b/pkg/cni/types/types.go @@ -86,6 +86,10 @@ type IPAMConf struct { // request to allocate pool's default gateway as // interface IP address for the container AllocateDefaultGateway bool + // request IP with the given index in the chunk allocated + // for the particular node as interface IP address for + // the container + AllocateIPWithIndex *int32 } `json:"-"` } @@ -109,6 +113,7 @@ type IPAMArgs struct { PoolNames []string `json:"poolNames"` PoolType string `json:"poolType"` AllocateDefaultGateway bool `json:"allocateDefaultGateway"` + AllocateIPWithIndex *int32 `json:"allocateIPWithIndex"` } // IPAMEnvArgs holds arguments from CNI_ARGS env variable @@ -191,11 +196,24 @@ func (cl *confLoader) LoadConf(args *skel.CmdArgs) (*NetConf, error) { if n.Args != nil && n.Args.ArgsCNI != nil { n.IPAM.Features.AllocateDefaultGateway = n.Args.ArgsCNI.AllocateDefaultGateway + if n.Args.ArgsCNI.AllocateIPWithIndex != nil && *n.Args.ArgsCNI.AllocateIPWithIndex < 0 { + return nil, fmt.Errorf("allocateIPWithIndex can't be negative") + } + n.IPAM.Features.AllocateIPWithIndex = n.Args.ArgsCNI.AllocateIPWithIndex } if n.IPAM.Features.AllocateDefaultGateway { if len(n.IPAM.RequestedIPs) > 0 { - return nil, fmt.Errorf("allocatedDefaultGateway can't be used together with static IP request") + return nil, fmt.Errorf("allocateDefaultGateway can't be used together with static IP request") + } + if n.IPAM.Features.AllocateIPWithIndex != nil { + return nil, fmt.Errorf("allocateDefaultGateway can't be used together allocateIPWithIndex") + } + } + + if n.IPAM.Features.AllocateIPWithIndex != nil { + if len(n.IPAM.RequestedIPs) > 0 { + return nil, fmt.Errorf("allocateIPWithIndex can't be used together with static IP request") } } diff --git a/pkg/cni/types/types_test.go b/pkg/cni/types/types_test.go index b1efcb8..bcf924e 100644 --- a/pkg/cni/types/types_test.go +++ b/pkg/cni/types/types_test.go @@ -170,18 +170,50 @@ var _ = Describe("Types Tests", func() { Entry("env variable", `{"name": "my-net", "ipam": {"confDir": %q}}`, "IP=192.168.1.1", []net.IP{net.ParseIP("192.168.1.1")}, true), - Entry("STDIN CNI args", `{"name": "my-net", + Entry("STDIN CNI args", `{"name": "my-net", "args": {"cni": {"ips": ["1.1.1.1", "2.2.2.2/24"]}}, "ipam": {"confDir": %q}}`, "", []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, true), - Entry("STDIN RuntimeConfig", `{"name": "my-net", + Entry("STDIN RuntimeConfig", `{"name": "my-net", "runtimeConfig": {"ips": ["1.1.1.1", "2.2.2.2/24"]}, "ipam": {"confDir": %q}}`, "", []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, true), - Entry("ipv6", `{"name": "my-net", + Entry("ipv6", `{"name": "my-net", "runtimeConfig": {"ips": ["fd52:2eb5:44::1"]}, "ipam": {"confDir": %q}}`, "", []net.IP{net.ParseIP("fd52:2eb5:44::1")}, true), - Entry("invalid ip", `{"name": "my-net", + Entry("invalid ip", `{"name": "my-net", "runtimeConfig": {"ips": ["adfdsaf"]}, "ipam": {"confDir": %q}}`, "", nil, false), + Entry("allocate default gateway and IP via env variable", + `{"name": "my-net", "args": {"cni": {"allocateDefaultGateway": true}},"ipam": {"confDir": %q}}`, + "IP=192.168.1.1", + []net.IP{net.ParseIP("192.168.1.1")}, false), + Entry("allocate default gateway and IP via STDIN CNI args", `{"name": "my-net", + "args": {"cni": {"ips": ["1.1.1.1", "2.2.2.2/24"], "allocateDefaultGateway": true}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, false), + Entry("allocate default gateway and IP via STDIN RuntimeConfig", `{"name": "my-net", + "runtimeConfig": {"ips": ["1.1.1.1", "2.2.2.2/24"]}, "args": {"cni": {"allocateDefaultGateway": true}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, false), + Entry("allocate default gateway and ipv6", `{"name": "my-net", + "runtimeConfig": {"ips": ["fd52:2eb5:44::1"]}, "args": {"cni": {"allocateDefaultGateway": true}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("fd52:2eb5:44::1")}, false), + Entry("allocate IP with index and IP via env variable", + `{"name": "my-net", "args": {"cni": {"allocateIPWithIndex": 1}},"ipam": {"confDir": %q}}`, + "IP=192.168.1.1", + []net.IP{net.ParseIP("192.168.1.1")}, false), + Entry("allocate IP with index and IP via STDIN CNI args", `{"name": "my-net", + "args": {"cni": {"ips": ["1.1.1.1", "2.2.2.2/24"], "allocateIPWithIndex": 1}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, false), + Entry("allocate IP with index and IP via STDIN RuntimeConfig", `{"name": "my-net", + "runtimeConfig": {"ips": ["1.1.1.1", "2.2.2.2/24"]}, "args": {"cni": {"allocateIPWithIndex": 1}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}, false), + Entry("allocate IP with index and ipv6", `{"name": "my-net", + "runtimeConfig": {"ips": ["fd52:2eb5:44::1"]}, "args": {"cni": {"allocateIPWithIndex": 1}}, + "ipam": {"confDir": %q}}`, "", + []net.IP{net.ParseIP("fd52:2eb5:44::1")}, false), ) DescribeTable("PoolName", func(fileContent string, stdinContent string, expectedValue []string, isValid bool) { @@ -210,7 +242,7 @@ var _ = Describe("Types Tests", func() { []string{"fromSTDIN"}, true), Entry("from STDIN CNI args", `{"poolName": "fromFile"}`, - `{"name": "my-net", "args":{"cni": {"poolNames": ["fromArgs", "fromArgs2"]}}, + `{"name": "my-net", "args":{"cni": {"poolNames": ["fromArgs", "fromArgs2"]}}, "ipam": {"confDir": %q, "poolName": "fromSTDIN"}}`, []string{"fromArgs", "fromArgs2"}, true), Entry("too many pools", @@ -234,9 +266,33 @@ var _ = Describe("Types Tests", func() { Entry("use IPPool by default", `{}`, `{"name": "my-net", "ipam": {"confDir": %q}}`, "ippool", true), Entry("from conf file", `{"poolType": "CIDRPool"}`, `{"name": "my-net", "ipam": {"confDir": %q}}`, "cidrpool", true), Entry("from STDIN", `{}`, `{"name": "my-net", "ipam": {"confDir": %q, "poolType": "cidrPool"}}`, "cidrpool", true), - Entry("from STDIN CNI Args", `{}`, `{"name": "my-net", + Entry("from STDIN CNI Args", `{}`, `{"name": "my-net", "args": {"cni": {"poolType":"cidrpool"}}, "ipam": {"confDir": %q}}`, "cidrpool", true), Entry("unknown type", `{}`, `{"name": "my-net", "ipam": {"confDir": %q, "poolType": "foobar"}}`, "", false), ) + It("errors if allocateIPWithIndex is negative", func() { + // write empty config file + err := os.WriteFile(path.Join(testConfDir, cniTypes.ConfFileName), []byte("{}"), 0o644) + Expect(err).ToNot(HaveOccurred()) + + // Load config + testConf := fmt.Sprintf(`{"name": "my-net", "ipam": {"confDir": %q}, "args": {"cni": {"allocateIPWithIndex": -1}}}`, testConfDir) + _, err = cniTypes.NewConfLoader().LoadConf(&skel.CmdArgs{StdinData: []byte(testConf), Args: testArgs}) + + // Validate + Expect(err).To(MatchError(ContainSubstring("allocateIPWithIndex can't be negative"))) + }) + It("errors if allocateDefaultGateway and allocateIPWithIndex are used together", func() { + // write empty config file + err := os.WriteFile(path.Join(testConfDir, cniTypes.ConfFileName), []byte("{}"), 0o644) + Expect(err).ToNot(HaveOccurred()) + + // Load config + testConf := fmt.Sprintf(`{"name": "my-net", "ipam": {"confDir": %q}, "args": {"cni": {"allocateIPWithIndex": 1, "allocateDefaultGateway": true}}}`, testConfDir) + _, err = cniTypes.NewConfLoader().LoadConf(&skel.CmdArgs{StdinData: []byte(testConf), Args: testArgs}) + + // Validate + Expect(err).To(MatchError(ContainSubstring("allocateDefaultGateway can't be used together allocateIPWithIndex"))) + }) }) }) diff --git a/pkg/ipam-node/handlers/allocate.go b/pkg/ipam-node/handlers/allocate.go index 9a7f712..45b1b3d 100644 --- a/pkg/ipam-node/handlers/allocate.go +++ b/pkg/ipam-node/handlers/allocate.go @@ -30,6 +30,7 @@ import ( nodev1 "github.com/Mellanox/nvidia-k8s-ipam/api/grpc/nvidia/ipam/node/v1" "github.com/Mellanox/nvidia-k8s-ipam/pkg/common" + "github.com/Mellanox/nvidia-k8s-ipam/pkg/ip" "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/allocator" storePkg "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/store" "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/types" @@ -132,25 +133,10 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger, return PoolAlloc{}, status.Errorf(codes.NotFound, "configuration for pool \"%s\", poolType \"%s\" not found", poolName, poolType) } - rangeStart := net.ParseIP(poolCfg.StartIP) - if rangeStart == nil { - return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, "invalid rangeStart") - } - rangeEnd := net.ParseIP(poolCfg.EndIP) - if rangeEnd == nil { - return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, "invalid rangeEnd") - } - _, subnet, err := net.ParseCIDR(poolCfg.Subnet) - if err != nil || subnet == nil || subnet.IP == nil || subnet.Mask == nil { - return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, "invalid subnet") + rangeSet, rangeStart, subnet, gateway, err := newRangeSetAndDependenciesForPoolCfg(poolCfg) + if err != nil { + return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, err.Error()) } - gateway := net.ParseIP(poolCfg.Gateway) - rangeSet := &allocator.RangeSet{allocator.Range{ - RangeStart: rangeStart, - RangeEnd: rangeEnd, - Subnet: cniTypes.IPNet(*subnet), - Gateway: gateway, - }} if err := rangeSet.Canonicalize(); err != nil { return PoolAlloc{}, poolCfgError(poolLog, poolName, poolType, fmt.Sprintf("invalid range config: %s", err.Error())) @@ -163,13 +149,29 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger, } } - if params.Features != nil && params.Features.AllocateDefaultGateway { - if gateway == nil { - return PoolAlloc{}, status.Errorf(codes.InvalidArgument, - "pool without gateway can't be used with allocate_default_gateway feature,"+ - "pool \"%s\", poolType \"%s\"", poolName, poolType) + if params.Features != nil { + if params.Features.AllocateDefaultGateway { + if gateway == nil { + return PoolAlloc{}, status.Errorf(codes.InvalidArgument, + "pool without gateway can't be used with allocate_default_gateway feature,"+ + "pool \"%s\", poolType \"%s\"", poolName, poolType) + } + selectedStaticIP = gateway + } + + if params.Features.AllocateIpWithIndex != nil { + selectedIP := ip.NextIPWithOffset(rangeStart, int64(*params.Features.AllocateIpWithIndex)) + if selectedIP.Equal(gateway) { + return PoolAlloc{}, status.Errorf(codes.InvalidArgument, + "requested IP index \"%d\" is the actual gateway, "+ + "use allocate_default_gateway feature instead", *params.Features.AllocateIpWithIndex) + } + if !rangeSet.Contains(selectedIP) { + return PoolAlloc{}, status.Errorf(codes.InvalidArgument, + "requested IP index \"%d\" is outside of the given chunk", *params.Features.AllocateIpWithIndex) + } + selectedStaticIP = selectedIP } - selectedStaticIP = gateway } exclusionRangeSet := make(allocator.RangeSet, 0, len(poolCfg.Exclusions)) @@ -191,12 +193,7 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger, CreateTime: time.Now().Format(time.RFC3339Nano), PoolConfigSnapshot: poolCfg.String(), } - if params.Metadata != nil { - allocMeta.PodUUID = params.Metadata.K8SPodUid - allocMeta.PodName = params.Metadata.K8SPodName - allocMeta.PodNamespace = params.Metadata.K8SPodNamespace - allocMeta.DeviceID = params.Metadata.DeviceId - } + setAllocMetadata(&allocMeta, params.Metadata) result, err := alloc.Allocate(params.CniContainerid, params.CniIfname, allocMeta, selectedStaticIP) if err != nil { poolLog.Error(err, "failed to allocate IP address") @@ -219,6 +216,38 @@ func (h *Handlers) allocateInPool(poolName string, reqLog logr.Logger, }, nil } +func newRangeSetAndDependenciesForPoolCfg(poolCfg *pool.Pool) (*allocator.RangeSet, net.IP, *net.IPNet, net.IP, error) { + rangeStart := net.ParseIP(poolCfg.StartIP) + if rangeStart == nil { + return nil, nil, nil, nil, errors.New("invalid rangeStart") + } + rangeEnd := net.ParseIP(poolCfg.EndIP) + if rangeEnd == nil { + return nil, nil, nil, nil, errors.New("invalid rangeEnd") + } + _, subnet, err := net.ParseCIDR(poolCfg.Subnet) + if err != nil || subnet == nil || subnet.IP == nil || subnet.Mask == nil { + return nil, nil, nil, nil, errors.New("invalid subnet") + } + gateway := net.ParseIP(poolCfg.Gateway) + rangeSet := &allocator.RangeSet{allocator.Range{ + RangeStart: rangeStart, + RangeEnd: rangeEnd, + Subnet: cniTypes.IPNet(*subnet), + Gateway: gateway, + }} + return rangeSet, rangeStart, subnet, gateway, nil +} + +func setAllocMetadata(allocMeta *types.ReservationMetadata, paramsMetadata *nodev1.IPAMMetadata) { + if paramsMetadata != nil { + allocMeta.PodUUID = paramsMetadata.K8SPodUid + allocMeta.PodName = paramsMetadata.K8SPodName + allocMeta.PodNamespace = paramsMetadata.K8SPodNamespace + allocMeta.DeviceID = paramsMetadata.DeviceId + } +} + func specificError(err error, poolName string, poolType string) error { if errors.Is(err, storePkg.ErrReservationAlreadyExist) { return status.Errorf(codes.AlreadyExists, diff --git a/pkg/ipam-node/handlers/handlers_test.go b/pkg/ipam-node/handlers/handlers_test.go index e1397a9..5848b48 100644 --- a/pkg/ipam-node/handlers/handlers_test.go +++ b/pkg/ipam-node/handlers/handlers_test.go @@ -20,6 +20,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "k8s.io/utils/ptr" current "github.com/containernetworking/cni/pkg/types/100" "github.com/stretchr/testify/mock" @@ -27,6 +28,7 @@ import ( "google.golang.org/grpc/status" nodev1 "github.com/Mellanox/nvidia-k8s-ipam/api/grpc/nvidia/ipam/node/v1" + "github.com/Mellanox/nvidia-k8s-ipam/pkg/ip" allocatorPkg "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/allocator" allocatorMockPkg "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/allocator/mocks" handlersPkg "github.com/Mellanox/nvidia-k8s-ipam/pkg/ipam-node/handlers" @@ -56,9 +58,9 @@ func getPoolConfigs() map[string]*pool.Pool { }, testPoolName2: {Name: testPoolName2, Subnet: "10.100.0.0/16", - StartIP: "10.100.0.2", + StartIP: "10.100.0.1", EndIP: "10.100.0.254", - Gateway: "10.100.0.1", + Gateway: "10.100.0.5", DefaultGateway: true, Routes: []pool.Route{ { @@ -176,6 +178,29 @@ var _ = Describe("Handlers", func() { HaveField("Gateway", "192.168.0.1"), ))) }) + It("Allocate IP with index", func() { + store.On("Open", mock.Anything).Return(session, nil) + poolManager.On("GetPoolByKey", testPoolName1).Return(getPoolConfigs()[testPoolName1]) + allocators[testPoolName1].On( + "Allocate", "id1", "net0", mock.Anything, ip.NormalizeIP(net.ParseIP("192.168.0.7"))).Return( + ¤t.IPConfig{ + Gateway: net.ParseIP("192.168.0.1"), + Address: getIPWithMask("192.168.0.7/16"), + }, nil) + session.On("Commit").Return(nil) + ipamParams := getValidIPAMParams() + ipamParams.Pools = []string{testPoolName1} + ipamParams.Features = &nodev1.IPAMFeatures{AllocateIpWithIndex: ptr.To[int32](5)} + resp, err := handlers.Allocate(ctx, &nodev1.AllocateRequest{Parameters: ipamParams}) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.Allocations).To(HaveLen(1)) + Expect(resp.Allocations).To(ContainElement( + And( + HaveField("Pool", testPoolName1), + HaveField("Ip", "192.168.0.7/16"), + HaveField("Gateway", "192.168.0.1"), + ))) + }) It("Allocate duplicate static routes", func() { store.On("Open", mock.Anything).Return(session, nil) allocators[testPoolName1].On("Allocate", "id1", "net0", mock.Anything, net.ParseIP("192.168.0.2")).Return( @@ -229,6 +254,26 @@ var _ = Describe("Handlers", func() { _, err := handlers.Allocate(ctx, &nodev1.AllocateRequest{Parameters: ipamParams}) Expect(err).To(MatchError(ContainSubstring("not all requested static IPs can be allocated"))) }) + It("Allocate failed: IP with index out of range", func() { + store.On("Open", mock.Anything).Return(session, nil) + poolManager.On("GetPoolByKey", testPoolName1).Return(getPoolConfigs()[testPoolName1]) + session.On("Cancel").Return() + ipamParams := getValidIPAMParams() + ipamParams.Pools = []string{testPoolName1} + ipamParams.Features = &nodev1.IPAMFeatures{AllocateIpWithIndex: ptr.To[int32](253)} + _, err := handlers.Allocate(ctx, &nodev1.AllocateRequest{Parameters: ipamParams}) + Expect(err).To(MatchError(ContainSubstring("requested IP index \"253\" is outside of the given chunk"))) + }) + It("Allocate failed: IP with index is the gateway", func() { + store.On("Open", mock.Anything).Return(session, nil) + poolManager.On("GetPoolByKey", testPoolName2).Return(getPoolConfigs()[testPoolName2]) + session.On("Cancel").Return() + ipamParams := getValidIPAMParams() + ipamParams.Pools = []string{testPoolName2} + ipamParams.Features = &nodev1.IPAMFeatures{AllocateIpWithIndex: ptr.To[int32](4)} + _, err := handlers.Allocate(ctx, &nodev1.AllocateRequest{Parameters: ipamParams}) + Expect(err).To(MatchError(ContainSubstring("requested IP index \"4\" is the actual gateway, use allocate_default_gateway feature instead"))) + }) It("Allocation failed: unknown pool", func() { store.On("Open", mock.Anything).Return(session, nil) poolManager.On("GetPoolByKey", testPoolName1).Return(nil)