@@ -2,42 +2,46 @@ package main
2
2
3
3
import (
4
4
"context"
5
- "crypto/ecdh"
6
- "crypto/x509"
7
- "encoding/pem"
5
+ "encoding/json"
8
6
"fmt"
9
7
"net/http"
10
8
"os"
11
9
"runtime"
10
+ "time"
12
11
13
12
re_filesystem "github.com/buildbarn/bb-remote-execution/pkg/filesystem"
13
+ "github.com/buildbarn/bb-storage/pkg/clock"
14
14
"github.com/buildbarn/bb-storage/pkg/filesystem"
15
15
"github.com/buildbarn/bb-storage/pkg/filesystem/path"
16
16
"github.com/buildbarn/bb-storage/pkg/global"
17
- bb_grpc "github.com/buildbarn/bb-storage/pkg/grpc"
18
17
bb_http "github.com/buildbarn/bb-storage/pkg/http"
19
18
"github.com/buildbarn/bb-storage/pkg/program"
19
+ "github.com/buildbarn/bb-storage/pkg/random"
20
20
"github.com/buildbarn/bb-storage/pkg/util"
21
21
"github.com/buildbarn/bonanza/pkg/evaluation"
22
22
model_analysis "github.com/buildbarn/bonanza/pkg/model/analysis"
23
23
model_core "github.com/buildbarn/bonanza/pkg/model/core"
24
24
"github.com/buildbarn/bonanza/pkg/model/encoding"
25
- build_pb "github.com/buildbarn/bonanza/pkg/proto/build"
26
25
"github.com/buildbarn/bonanza/pkg/proto/configuration/bonanza_builder"
27
26
model_analysis_pb "github.com/buildbarn/bonanza/pkg/proto/model/analysis"
27
+ model_build_pb "github.com/buildbarn/bonanza/pkg/proto/model/build"
28
+ model_command_pb "github.com/buildbarn/bonanza/pkg/proto/model/command"
28
29
remoteexecution_pb "github.com/buildbarn/bonanza/pkg/proto/remoteexecution"
30
+ remoteworker_pb "github.com/buildbarn/bonanza/pkg/proto/remoteworker"
29
31
dag_pb "github.com/buildbarn/bonanza/pkg/proto/storage/dag"
30
32
object_pb "github.com/buildbarn/bonanza/pkg/proto/storage/object"
33
+ remoteexecution "github.com/buildbarn/bonanza/pkg/remoteexecution"
34
+ "github.com/buildbarn/bonanza/pkg/remoteworker"
31
35
"github.com/buildbarn/bonanza/pkg/storage/dag"
32
36
"github.com/buildbarn/bonanza/pkg/storage/object"
33
37
object_grpc "github.com/buildbarn/bonanza/pkg/storage/object/grpc"
34
38
object_namespacemapping "github.com/buildbarn/bonanza/pkg/storage/object/namespacemapping"
35
39
36
40
"golang.org/x/sync/semaphore"
37
- "google.golang.org/grpc"
38
41
"google.golang.org/grpc/codes"
39
42
"google.golang.org/grpc/status"
40
43
"google.golang.org/protobuf/proto"
44
+ "google.golang.org/protobuf/types/known/emptypb"
41
45
)
42
46
43
47
func main () {
@@ -82,125 +86,147 @@ func main() {
82
86
return util .StatusWrap (err , "Failed to create execution gRPC client" )
83
87
}
84
88
85
- executionClientPrivateKeyBlock , _ := pem . Decode ([]byte (configuration .ExecutionClientPrivateKey ))
86
- if executionClientPrivateKeyBlock = = nil {
87
- return status . Error ( codes . InvalidArgument , "Execution client private key does not contain a PEM block " )
89
+ executionClientPrivateKey , err := remoteexecution . ParseECDHPrivateKey ([]byte (configuration .ExecutionClientPrivateKey ))
90
+ if err ! = nil {
91
+ return util . StatusWrap ( err , "Failed to parse execution client private key " )
88
92
}
89
- if executionClientPrivateKeyBlock .Type != "PRIVATE KEY" {
90
- return status .Error (codes .InvalidArgument , "Execution client private key PEM block is not of type PRIVATE KEY" )
93
+ executionClientCertificateChain , err := remoteexecution .ParseCertificateChain ([]byte (configuration .ExecutionClientCertificateChain ))
94
+ if err != nil {
95
+ return util .StatusWrap (err , "Failed to parse execution client certificate chain" )
91
96
}
92
- executionClientPrivateKey , err := x509 .ParsePKCS8PrivateKey (executionClientPrivateKeyBlock .Bytes )
97
+
98
+ remoteWorkerConnection , err := grpcClientFactory .NewClientFromConfiguration (configuration .RemoteWorkerGrpcClient )
93
99
if err != nil {
94
- return util .StatusWrap (err , "Failed to parse execution client private key " )
100
+ return util .StatusWrap (err , "Failed to create remote worker RPC client " )
95
101
}
96
- executionClientECDHPrivateKey , ok := executionClientPrivateKey .(* ecdh.PrivateKey )
97
- if ! ok {
98
- return status .Error (codes .InvalidArgument , "Execution client private key is not an ECDH private key" )
102
+ remoteWorkerClient := remoteworker_pb .NewOperationQueueClient (remoteWorkerConnection )
103
+
104
+ platformPrivateKeys , err := remoteworker .ParsePlatformPrivateKeys (configuration .PlatformPrivateKeys )
105
+ if err != nil {
106
+ return err
99
107
}
100
- var executionClientCertificates [][]byte
101
- for certificateBlock , remainder := pem .Decode ([]byte (configuration .ExecutionClientCertificateChain )); certificateBlock != nil ; certificateBlock , remainder = pem .Decode (remainder ) {
102
- if certificateBlock .Type != "CERTIFICATE" {
103
- return status .Error (codes .InvalidArgument , "Execution client certificate PEM block is not of type CERTIFICATE" )
104
- }
105
- executionClientCertificates = append (executionClientCertificates , certificateBlock .Bytes )
106
- }
107
-
108
- if err := bb_grpc .NewServersFromConfigurationAndServe (
109
- configuration .GrpcServers ,
110
- func (s grpc.ServiceRegistrar ) {
111
- build_pb .RegisterBuilderServer (s , & builderServer {
112
- objectDownloader : objectDownloader ,
113
- dagUploaderClient : dag_pb .NewUploaderClient (storageGRPCClient ),
114
- objectContentsWalkerSemaphore : semaphore .NewWeighted (int64 (runtime .NumCPU ())),
115
- httpClient : & http.Client {
116
- Transport : bb_http .NewMetricsRoundTripper (roundTripper , "Builder" ),
117
- },
118
- filePool : filePool ,
119
- cacheDirectory : cacheDirectory ,
120
- executionClient : remoteexecution_pb .NewExecutionClient (executionGRPCClient ),
121
- executionClientPrivateKey : executionClientECDHPrivateKey ,
122
- executionClientCertificates : executionClientCertificates ,
123
- })
108
+ clientCertificateAuthorities , err := remoteworker .ParseClientCertificateAuthorities (configuration .ClientCertificateAuthorities )
109
+ if err != nil {
110
+ return err
111
+ }
112
+ workerName , err := json .Marshal (configuration .WorkerId )
113
+ if err != nil {
114
+ return util .StatusWrap (err , "Failed to marshal worker ID" )
115
+ }
116
+
117
+ executor := & builderExecutor {
118
+ objectDownloader : objectDownloader ,
119
+ dagUploaderClient : dag_pb .NewUploaderClient (storageGRPCClient ),
120
+ objectContentsWalkerSemaphore : semaphore .NewWeighted (int64 (runtime .NumCPU ())),
121
+ httpClient : & http.Client {
122
+ Transport : bb_http .NewMetricsRoundTripper (roundTripper , "Builder" ),
124
123
},
125
- siblingsGroup ,
126
- ); err != nil {
127
- return util .StatusWrap (err , "gRPC server failure" )
124
+ filePool : filePool ,
125
+ cacheDirectory : cacheDirectory ,
126
+ executionClient : remoteexecution .NewClient [* model_command_pb.Action , emptypb.Empty , * model_command_pb.Result ](
127
+ remoteexecution_pb .NewExecutionClient (executionGRPCClient ),
128
+ executionClientPrivateKey ,
129
+ executionClientCertificateChain ,
130
+ ),
128
131
}
132
+ client , err := remoteworker .NewClient (
133
+ remoteWorkerClient ,
134
+ executor ,
135
+ clock .SystemClock ,
136
+ random .CryptoThreadSafeGenerator ,
137
+ platformPrivateKeys ,
138
+ clientCertificateAuthorities ,
139
+ configuration .WorkerId ,
140
+ /* sizeClass = */ 0 ,
141
+ /* isLargestSizeClass = */ true ,
142
+ )
143
+ if err != nil {
144
+ return util .StatusWrap (err , "Failed to create remote worker client" )
145
+ }
146
+ remoteworker .LaunchWorkerThread (siblingsGroup , client .Run , string (workerName ))
129
147
130
148
lifecycleState .MarkReadyAndWait (siblingsGroup )
131
149
return nil
132
150
})
133
151
}
134
152
135
- type builderServer struct {
153
+ type builderExecutor struct {
136
154
objectDownloader object.Downloader [object.GlobalReference ]
137
155
dagUploaderClient dag_pb.UploaderClient
138
156
objectContentsWalkerSemaphore * semaphore.Weighted
139
157
httpClient * http.Client
140
158
filePool re_filesystem.FilePool
141
159
cacheDirectory filesystem.Directory
142
- executionClient remoteexecution_pb.ExecutionClient
143
- executionClientPrivateKey * ecdh.PrivateKey
144
- executionClientCertificates [][]byte
160
+ executionClient * remoteexecution.Client [* model_command_pb.Action , emptypb.Empty , * emptypb.Empty , * model_command_pb.Result ]
145
161
}
146
162
147
- func (s * builderServer ) PerformBuild (request * build_pb.PerformBuildRequest , server build_pb.Builder_PerformBuildServer ) error {
148
- ctx := server .Context ()
163
+ func (e * builderExecutor ) CheckReadiness (ctx context.Context ) error {
164
+ return nil
165
+ }
149
166
150
- namespace , err := object .NewNamespace (request .Namespace )
167
+ func (e * builderExecutor ) Execute (ctx context.Context , action * model_build_pb.Action , executionTimeout time.Duration , executionEvents chan <- proto.Message ) (proto.Message , time.Duration , remoteworker_pb.CurrentState_Completed_Result ) {
168
+ namespace , err := object .NewNamespace (action .Namespace )
151
169
if err != nil {
152
- return util .StatusWrap (err , "Invalid namespace" )
170
+ return & model_build_pb.Result {
171
+ Status : status .Convert (util .StatusWrap (err , "Invalid namespace" )).Proto (),
172
+ }, 0 , remoteworker_pb .CurrentState_Completed_FAILED
153
173
}
154
174
instanceName := namespace .InstanceName
155
- objectDownloader := object_namespacemapping .NewNamespaceAddingDownloader (s .objectDownloader , namespace )
156
- buildSpecificationReference , err := namespace .NewGlobalReference (request .BuildSpecificationReference )
175
+ objectDownloader := object_namespacemapping .NewNamespaceAddingDownloader (e .objectDownloader , namespace )
176
+ buildSpecificationReference , err := namespace .NewGlobalReference (action .BuildSpecificationReference )
157
177
if err != nil {
158
- return util .StatusWrap (err , "Invalid build specification reference" )
178
+ return & model_build_pb.Result {
179
+ Status : status .Convert (util .StatusWrap (err , "Invalid build specification reference" )).Proto (),
180
+ }, 0 , remoteworker_pb .CurrentState_Completed_FAILED
159
181
}
160
182
buildSpecificationEncoder , err := encoding .NewBinaryEncoderFromProto (
161
- request .BuildSpecificationEncoders ,
183
+ action .BuildSpecificationEncoders ,
162
184
uint32 (namespace .ReferenceFormat .GetMaximumObjectSizeBytes ()),
163
185
)
164
186
if err != nil {
165
- return util .StatusWrap (err , "Invalid build specification encoders" )
187
+ return & model_build_pb.Result {
188
+ Status : status .Convert (util .StatusWrap (err , "Invalid build specification encoder" )).Proto (),
189
+ }, 0 , remoteworker_pb .CurrentState_Completed_FAILED
166
190
}
167
191
value , err := evaluation .FullyComputeValue (
168
192
ctx ,
169
193
model_analysis .NewTypedComputer (model_analysis .NewBaseComputer (
170
194
objectDownloader ,
171
195
buildSpecificationReference ,
172
196
buildSpecificationEncoder ,
173
- s .httpClient ,
174
- s .filePool ,
175
- s .cacheDirectory ,
176
- s .executionClient ,
177
- s .executionClientPrivateKey ,
178
- s .executionClientCertificates ,
197
+ e .httpClient ,
198
+ e .filePool ,
199
+ e .cacheDirectory ,
200
+ e .executionClient ,
179
201
)),
180
202
model_core.NewSimpleMessage [proto.Message ](& model_analysis_pb.BuildResult_Key {}),
181
203
func (references []object.LocalReference , objectContentsWalkers []dag.ObjectContentsWalker ) error {
182
204
for i , reference := range references {
183
205
if err := dag .UploadDAG (
184
206
ctx ,
185
- s .dagUploaderClient ,
207
+ e .dagUploaderClient ,
186
208
object.GlobalReference {
187
209
InstanceName : instanceName ,
188
210
LocalReference : reference ,
189
211
},
190
212
objectContentsWalkers [i ],
191
- s .objectContentsWalkerSemaphore ,
213
+ e .objectContentsWalkerSemaphore ,
192
214
// Assume everything we attempt
193
215
// to upload is memory backed.
194
216
object .Unlimited ,
195
217
); err != nil {
196
- return fmt .Errorf ("failed to store DAG with reference %s : %w" , reference .String (), err )
218
+ return fmt .Errorf ("failed to store DAG with reference %e : %w" , reference .String (), err )
197
219
}
198
220
}
199
221
return nil
200
222
},
201
223
)
202
224
if err != nil {
203
- return err
225
+ return & model_build_pb.Result {
226
+ Status : status .Convert (err ).Proto (),
227
+ }, 0 , remoteworker_pb .CurrentState_Completed_FAILED
204
228
}
205
- return status .Errorf (codes .Internal , "XXX: %s" , value )
229
+ return & model_build_pb.Result {
230
+ Status : status .Newf (codes .Internal , "TODO: %s" , value ).Proto (),
231
+ }, 0 , remoteworker_pb .CurrentState_Completed_FAILED
206
232
}
0 commit comments