12 "git.curoverse.com/arvados.git/sdk/go/arvados"
23 BlobSignatureTTL arvados.Duration
24 BlobSigningKeyFile string
25 RequireSignatures bool
26 SystemAuthTokenFile string
28 TrashLifetime arvados.Duration
29 TrashCheckInterval arvados.Duration
34 systemAuthToken string
37 var theConfig = DefaultConfig()
39 // DefaultConfig returns the default configuration.
40 func DefaultConfig() *Config {
44 RequireSignatures: true,
45 BlobSignatureTTL: arvados.Duration(14 * 24 * time.Hour),
46 TrashLifetime: arvados.Duration(14 * 24 * time.Hour),
47 TrashCheckInterval: arvados.Duration(24 * time.Hour),
52 // Start should be called exactly once: after setting all public
53 // fields, and before using the config.
54 func (cfg *Config) Start() error {
55 if cfg.MaxBuffers < 0 {
56 return fmt.Errorf("MaxBuffers must be greater than zero")
58 bufs = newBufferPool(cfg.MaxBuffers, BlockSize)
60 if cfg.MaxRequests < 1 {
61 cfg.MaxRequests = cfg.MaxBuffers * 2
62 log.Printf("MaxRequests <1 or not specified; defaulting to MaxBuffers * 2 == %d", cfg.MaxRequests)
65 if cfg.BlobSigningKeyFile != "" {
66 buf, err := ioutil.ReadFile(cfg.BlobSigningKeyFile)
68 return fmt.Errorf("reading blob signing key file: %s", err)
70 cfg.blobSigningKey = bytes.TrimSpace(buf)
71 if len(cfg.blobSigningKey) == 0 {
72 return fmt.Errorf("blob signing key file %q is empty", cfg.BlobSigningKeyFile)
74 } else if cfg.RequireSignatures {
75 return fmt.Errorf("cannot enable RequireSignatures (-enforce-permissions) without a blob signing key")
77 log.Println("Running without a blob signing key. Block locators " +
78 "returned by this server will not be signed, and will be rejected " +
79 "by a server that enforces permissions.")
80 log.Println("To fix this, use the BlobSigningKeyFile config entry.")
83 if fn := cfg.SystemAuthTokenFile; fn != "" {
84 buf, err := ioutil.ReadFile(fn)
86 return fmt.Errorf("cannot read system auth token file %q: %s", fn, err)
88 cfg.systemAuthToken = strings.TrimSpace(string(buf))
92 log.Print("Trash/delete features are enabled. WARNING: this has not " +
93 "been extensively tested. You should disable this unless you can afford to lose data.")
96 if len(cfg.Volumes) == 0 {
97 if (&unixVolumeAdder{cfg}).Discover() == 0 {
98 return fmt.Errorf("no volumes found")
101 for _, v := range cfg.Volumes {
102 if err := v.Start(); err != nil {
103 return fmt.Errorf("volume %s: %s", v, err)
105 log.Printf("Using volume %v (writable=%v)", v, v.Writable())
110 // VolumeTypes is built up by init() funcs in the source files that
111 // define the volume types.
112 var VolumeTypes = []func() VolumeWithExamples{}
114 type VolumeList []Volume
116 // UnmarshalJSON, given an array of objects, deserializes each object
117 // as the volume type indicated by the object's Type field.
118 func (vols *VolumeList) UnmarshalJSON(data []byte) error {
119 typeMap := map[string]func() VolumeWithExamples{}
120 for _, factory := range VolumeTypes {
121 t := factory().Type()
122 if _, ok := typeMap[t]; ok {
123 log.Fatal("volume type %+q is claimed by multiple VolumeTypes")
128 var mapList []map[string]interface{}
129 err := json.Unmarshal(data, &mapList)
133 for _, mapIn := range mapList {
134 typeIn, ok := mapIn["Type"].(string)
136 return fmt.Errorf("invalid volume type %+v", mapIn["Type"])
138 factory, ok := typeMap[typeIn]
140 return fmt.Errorf("unsupported volume type %+q", typeIn)
142 data, err := json.Marshal(mapIn)
147 err = json.Unmarshal(data, vol)
151 *vols = append(*vols, vol)
156 // MarshalJSON adds a "Type" field to each volume corresponding to its
158 func (vl *VolumeList) MarshalJSON() ([]byte, error) {
160 for _, vs := range *vl {
161 j, err := json.Marshal(vs)
166 data = append(data, byte(','))
168 t, err := json.Marshal(vs.Type())
172 data = append(data, j[0])
173 data = append(data, []byte(`"Type":`)...)
174 data = append(data, t...)
175 data = append(data, byte(','))
176 data = append(data, j[1:]...)
178 return append(data, byte(']')), nil