Merge branch 'master' into 14715-keepprox-config
authorEric Biagiotti <ebiagiotti@veritasgenetics.com>
Wed, 14 Aug 2019 14:49:48 +0000 (10:49 -0400)
committerEric Biagiotti <ebiagiotti@veritasgenetics.com>
Wed, 14 Aug 2019 14:49:48 +0000 (10:49 -0400)
refs #14715

Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti@veritasgenetics.com>

1  2 
doc/admin/upgrading.html.textile.liquid
lib/config/config.default.yml
lib/config/deprecated.go
lib/config/export.go
lib/config/generated_config.go
lib/config/load.go
sdk/go/arvados/config.go
sdk/python/tests/run_test_server.py
tools/arvbox/lib/arvbox/docker/cluster-config.sh
tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service

index 7ea1b10fae1492679fd942ade2a2d22c51ea512e,8c2ca765769eb18c6eb79bbe078c0dcde8ba08bc..28f08db4dd3ffbaf41c2385c59041010b22f22cb
@@@ -39,15 -39,21 +39,25 @@@ table(table table-bordered table-conden
  |"v1.1.4":#v1_1_4|"v1.1.3":#v1_1_3|"v1.1.2":#v1_1_2|"v1.1.1":#v1_1_1|"v1.1.0":#v1_1_0|
  |\5. "older":#older|
  
- h3(#master). development master (as of 2019-06-07)
+ h3(#master). development master (as of 2019-08-12)
+ h4. Keep-web dropped support on command line flags configuration
+ As we're migrating to a central cluster configuration file, the already deprecated way of getting configurations via environment variables and command line flags isn't valid anymore. Current keep-web supports both the now legacy @keep-web.yml@ config format (used by Arvados 1.4) and the new cluster config file format. Please check "keep-web's install guide":{{site.baseurl}}/install/install-keep-web.html for more details.
+ h4. Jobs API is read-only
+ (task "#15133":https://dev.arvados.org/issues/15133 ) The legacy 'jobs' API is now read-only.  It has long been superceded by containers / container_requests (aka crunch v2).  Arvados installations since the end of 2017 (v1.1.0) have probably only used containers, and are unaffected by this change.
+ So that older Arvados sites don't lose access to legacy records, the API has been converted to read-only.  Creating and updating jobs (and related types job_task, pipeline_template and pipeline_instance) is disabled and much of the business logic related has been removed, along with various other code specific to the jobs API.  Specifically, the following programs associated with the jobs API have been removed: @crunch-dispatch.rb@, @crunch-job@, @crunchrunner@, @arv-run-pipeline-instance@, @arv-run@.
  
 +h4. Keepproxy configuration migration
 +
 +Keepproxy can now be configured using the centralized config at @/etc/arvados/config.yml@. Some configuration options are no longer supported. Please see "keepproxy's config migration guide":{{site.baseurl}}/admin/config-migration.html#keepproxy for more details.
 +
  h4. No longer stripping ':' from strings in serialized database columns
  
 (bug #15311) Strings read from serialized columns in the database with a leading ':' would have the ':' stripped after loading the record.  This behavior existed due to legacy serialization behavior which stored Ruby symbols with a leading ':'.  Unfortunately this corrupted fields where the leading ":" was intentional.  This behavior has been removed.
(bug "#15311":https://dev.arvados.org/issues/15311 ) Strings read from serialized columns in the database with a leading ':' would have the ':' stripped after loading the record.  This behavior existed due to legacy serialization behavior which stored Ruby symbols with a leading ':'.  Unfortunately this corrupted fields where the leading ":" was intentional.  This behavior has been removed.
  
  You can test if any records in your database are affected by going to the API server directory and running @bundle exec rake symbols:check@.  This will report which records contain fields with a leading ':' that would previously have been stripped.  If there are records to be updated, you can update the database using @bundle exec rake symbols:stringify@.
  
index 6da5344fa3a55920894def50df20acc68d4bcd02,dfdd0310448826174b83c1e005d2d22dcce9e062..163cd87ec5107ee826e1b971eac94fc4f8b1892d
@@@ -206,17 -206,14 +206,17 @@@ Clusters
        WebsocketClientEventQueue: 64
        WebsocketServerEventQueue: 4
  
 +      # Timeout on requests to internal Keep services.
 +      KeepServiceRequestTimeout: 15s
 +
      Users:
        # Config parameters to automatically setup new users.  If enabled,
        # this users will be able to self-activate.  Enable this if you want
        # to run an open instance where anyone can create an account and use
        # the system without requiring manual approval.
        #
-       # The params auto_setup_new_users_with_* are meaningful only when auto_setup_new_users is turned on.
-       # auto_setup_name_blacklist is a list of usernames to be blacklisted for auto setup.
+       # The params AutoSetupNewUsersWith* are meaningful only when AutoSetupNewUsers is turned on.
+       # AutoSetupUsernameBlacklist is a list of usernames to be blacklisted for auto setup.
        AutoSetupNewUsers: false
        AutoSetupNewUsersWithVmUUID: ""
        AutoSetupNewUsersWithRepository: false
          syslog: {}
          SAMPLE: {}
  
-       # When new_users_are_active is set to true, new users will be active
+       # When NewUsersAreActive is set to true, new users will be active
        # immediately.  This skips the "self-activate" step which enforces
        # user agreements.  Should only be enabled for development.
        NewUsersAreActive: false
        # should be an address associated with a Google account.
        AutoAdminUserWithEmail: ""
  
-       # If auto_admin_first_user is set to true, the first user to log in when no
+       # If AutoAdminFirstUser is set to true, the first user to log in when no
        # other admin users exist will automatically become an admin user.
        AutoAdminFirstUser: false
  
        NewUserNotificationRecipients: {}
        NewInactiveUserNotificationRecipients: {}
  
-       # Set anonymous_user_token to enable anonymous user access. You can get
+       # Set AnonymousUserToken to enable anonymous user access. You can get
        # the token by running "bundle exec ./script/get_anonymous_user_token.rb"
        # in the directory where your API server is running.
        AnonymousUserToken: ""
  
        # Maximum number of log rows to delete in a single SQL transaction.
        #
-       # If max_audit_log_delete_batch is 0, log entries will never be
+       # If MaxDeleteBatch is 0, log entries will never be
        # deleted by Arvados. Cleanup can be done by an external process
        # without affecting any Arvados system processes, as long as very
        # recent (<5 minutes old) logs are not deleted.
        # identical to the permission key given to Keep. IMPORTANT: This is
        # a site secret. It should be at least 50 characters.
        #
-       # Modifying blob_signing_key will invalidate all existing
+       # Modifying BlobSigningKey will invalidate all existing
        # signatures, which can cause programs to fail (e.g., arv-put,
        # arv-get, and Crunch jobs).  To avoid errors, rotate keys only when
        # no such processes are running.
        # keepstore servers.  Otherwise, reading data blocks and saving
        # collections will fail with HTTP 403 permission errors.
        #
-       # Modifying blob_signature_ttl invalidates existing signatures; see
-       # blob_signing_key note above.
+       # Modifying BlobSigningTTL invalidates existing signatures; see
+       # BlobSigningKey note above.
        #
        # The default is 2 weeks.
        BlobSigningTTL: 336h
  
        # Default lifetime for ephemeral collections: 2 weeks. This must not
-       # be less than blob_signature_ttl.
+       # be less than BlobSigningTTL.
        DefaultTrashLifetime: 336h
  
        # Interval (seconds) between trash sweeps. During a trash sweep,
  
        # If true, enable collection versioning.
        # When a collection's preserve_version field is true or the current version
-       # is older than the amount of seconds defined on preserve_version_if_idle,
+       # is older than the amount of seconds defined on PreserveVersionIfIdle,
        # a snapshot of the collection's previous state is created and linked to
        # the current collection.
        CollectionVersioning: false
        # The default setting (false) is appropriate for a multi-user site.
        TrustAllContent: false
  
+       # Cache parameters for WebDAV content serving:
+       # * TTL: Maximum time to cache manifests and permission checks.
+       # * UUIDTTL: Maximum time to cache collection state.
+       # * MaxBlockEntries: Maximum number of block cache entries.
+       # * MaxCollectionEntries: Maximum number of collection cache entries.
+       # * MaxCollectionBytes: Approximate memory limit for collection cache.
+       # * MaxPermissionEntries: Maximum number of permission cache entries.
+       # * MaxUUIDEntries: Maximum number of UUID cache entries.
+       WebDAVCache:
+         TTL: 300s
+         UUIDTTL: 5s
+         MaxBlockEntries:      4
+         MaxCollectionEntries: 1000
+         MaxCollectionBytes:   100000000
+         MaxPermissionEntries: 1000
+         MaxUUIDEntries:       1000
      Login:
        # These settings are provided by your OAuth2 provider (e.g.,
        # sso-provider).
            AssignNodeHostname: "compute%<slot_number>d"
  
        JobsAPI:
-         # Enable the legacy Jobs API.  This value must be a string.
+         # Enable the legacy 'jobs' API (crunch v1).  This value must be a string.
+         #
+         # Note: this only enables read-only access, creating new
+         # legacy jobs and pipelines is not supported.
+         #
          # 'auto' -- (default) enable the Jobs API only if it has been used before
          #         (i.e., there are job records in the database)
          # 'true' -- enable the Jobs API despite lack of existing records.
          # {git_repositories_dir}/arvados/.git
          GitInternalDir: /var/lib/arvados/internal.git
  
-         # Docker image to be used when none found in runtime_constraints of a job
-         DefaultDockerImage: ""
-         # none or slurm_immediate
-         CrunchJobWrapper: none
-         # username, or false = do not set uid when running jobs.
-         CrunchJobUser: crunch
-         # The web service must be able to create/write this file, and
-         # crunch-job must be able to stat() it.
-         CrunchRefreshTrigger: /tmp/crunch_refresh_trigger
-         # Control job reuse behavior when two completed jobs match the
-         # search criteria and have different outputs.
-         #
-         # If true, in case of a conflict, reuse the earliest job (this is
-         # similar to container reuse behavior).
-         #
-         # If false, in case of a conflict, do not reuse any completed job,
-         # but do reuse an already-running job if available (this is the
-         # original job reuse behavior, and is still the default).
-         ReuseJobIfOutputsDiffer: false
        CloudVMs:
          # Enable the cloud scheduler (experimental).
          Enable: false
diff --combined lib/config/deprecated.go
index 4e7b85ec5d9c43644ddfc0e451ec9703df70dce3,019979d39fe2d068c4a196d398e5111d137c35c1..df872111db2adf8ff1bc504fd0a5b2f31f2b14a6
@@@ -327,74 -327,72 +327,144 @@@ func (ldr *Loader) loadOldWebsocketConf
        return nil
  }
  
 +type oldKeepProxyConfig struct {
 +      Client          *arvados.Client
 +      Listen          *string
 +      DisableGet      *bool
 +      DisablePut      *bool
 +      DefaultReplicas *int
 +      Timeout         *arvados.Duration
 +      PIDFile         *string
 +      Debug           *bool
 +      ManagementToken *string
 +}
 +
 +const defaultKeepproxyConfigPath = "/etc/arvados/keepproxy/keepproxy.yml"
 +
 +func (ldr *Loader) loadOldKeepproxyConfig(cfg *arvados.Config) error {
 +      if ldr.KeepproxyPath == "" {
 +              return nil
 +      }
 +      var oc oldKeepProxyConfig
 +      err := ldr.loadOldConfigHelper("keepproxy", ldr.KeepproxyPath, &oc)
 +      if os.IsNotExist(err) && ldr.KeepproxyPath == defaultKeepproxyConfigPath {
 +              return nil
 +      } else if err != nil {
 +              return err
 +      }
 +
 +      cluster, err := cfg.GetCluster("")
 +      if err != nil {
 +              return err
 +      }
 +
 +      loadOldClientConfig(cluster, oc.Client)
 +
 +      if oc.Listen != nil {
 +              cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: *oc.Listen}] = arvados.ServiceInstance{}
 +      }
 +      if oc.DefaultReplicas != nil {
 +              cluster.Collections.DefaultReplication = *oc.DefaultReplicas
 +      }
 +      if oc.Timeout != nil {
 +              cluster.API.KeepServiceRequestTimeout = *oc.Timeout
 +      }
 +      if oc.Debug != nil {
 +              if *oc.Debug && cluster.SystemLogs.LogLevel != "debug" {
 +                      cluster.SystemLogs.LogLevel = "debug"
 +              } else if !*oc.Debug && cluster.SystemLogs.LogLevel != "info" {
 +                      cluster.SystemLogs.LogLevel = "info"
 +              }
 +      }
 +      if oc.ManagementToken != nil {
 +              cluster.ManagementToken = *oc.ManagementToken
 +      }
 +
 +      // The following legacy options are no longer supported. If they are set to
 +      // true or PIDFile has a value, error out and notify the user
 +      unsupportedEntry := func(cfgEntry string) error {
 +              return fmt.Errorf("the keepproxy %s configuration option is no longer supported, please remove it from your configuration file", cfgEntry)
 +      }
 +      if oc.DisableGet != nil && *oc.DisableGet {
 +              return unsupportedEntry("DisableGet")
 +      }
 +      if oc.DisablePut != nil && *oc.DisablePut {
 +              return unsupportedEntry("DisablePut")
 +      }
 +      if oc.PIDFile != nil && *oc.PIDFile != "" {
 +              return unsupportedEntry("PIDFile")
 +      }
 +
 +      cfg.Clusters[cluster.ClusterID] = *cluster
 +      return nil
 +}
++
+ const defaultKeepWebConfigPath = "/etc/arvados/keep-web/keep-web.yml"
+ type oldKeepWebConfig struct {
+       Client *arvados.Client
+       Listen string
+       AnonymousTokens    []string
+       AttachmentOnlyHost string
+       TrustAllContent    bool
+       Cache struct {
+               TTL                  arvados.Duration
+               UUIDTTL              arvados.Duration
+               MaxCollectionEntries int
+               MaxCollectionBytes   int64
+               MaxPermissionEntries int
+               MaxUUIDEntries       int
+       }
+       // Hack to support old command line flag, which is a bool
+       // meaning "get actual token from environment".
+       deprecatedAllowAnonymous bool
+       // Authorization token to be included in all health check requests.
+       ManagementToken string
+ }
+ func (ldr *Loader) loadOldKeepWebConfig(cfg *arvados.Config) error {
+       if ldr.KeepWebPath == "" {
+               return nil
+       }
+       var oc oldKeepWebConfig
+       err := ldr.loadOldConfigHelper("keep-web", ldr.KeepWebPath, &oc)
+       if os.IsNotExist(err) && ldr.KeepWebPath == defaultKeepWebConfigPath {
+               return nil
+       } else if err != nil {
+               return err
+       }
+       cluster, err := cfg.GetCluster("")
+       if err != nil {
+               return err
+       }
+       loadOldClientConfig(cluster, oc.Client)
+       cluster.Services.WebDAV.InternalURLs[arvados.URL{Host: oc.Listen}] = arvados.ServiceInstance{}
+       cluster.Services.WebDAVDownload.InternalURLs[arvados.URL{Host: oc.Listen}] = arvados.ServiceInstance{}
+       cluster.Services.WebDAVDownload.ExternalURL = arvados.URL{Host: oc.AttachmentOnlyHost}
+       cluster.TLS.Insecure = oc.Client.Insecure
+       cluster.ManagementToken = oc.ManagementToken
+       cluster.Collections.TrustAllContent = oc.TrustAllContent
+       cluster.Collections.WebDAVCache.TTL = oc.Cache.TTL
+       cluster.Collections.WebDAVCache.UUIDTTL = oc.Cache.UUIDTTL
+       cluster.Collections.WebDAVCache.MaxCollectionEntries = oc.Cache.MaxCollectionEntries
+       cluster.Collections.WebDAVCache.MaxCollectionBytes = oc.Cache.MaxCollectionBytes
+       cluster.Collections.WebDAVCache.MaxPermissionEntries = oc.Cache.MaxPermissionEntries
+       cluster.Collections.WebDAVCache.MaxUUIDEntries = oc.Cache.MaxUUIDEntries
+       if len(oc.AnonymousTokens) > 0 {
+               cluster.Users.AnonymousUserToken = oc.AnonymousTokens[0]
+               if len(oc.AnonymousTokens) > 1 {
+                       ldr.Logger.Warn("More than 1 anonymous tokens configured, using only the first and discarding the rest.")
+               }
+       }
+       cfg.Clusters[cluster.ClusterID] = *cluster
+       return nil
+ }
diff --combined lib/config/export.go
index 82b48b36b0fc074dc82b551985e58a7d08f883bd,a0be827f040e61dd8052def574a589404fab216d..6eb4fbe5f570d4abf9ffd885f1ab0d822acf7fa2
@@@ -72,7 -72,6 +72,7 @@@ var whitelist = map[string]bool
        "API.WebsocketClientEventQueue":                false,
        "API.SendTimeout":                              true,
        "API.WebsocketServerEventQueue":                false,
 +      "API.KeepServiceRequestTimeout":                false,
        "AuditLogs":                                    false,
        "AuditLogs.MaxAge":                             false,
        "AuditLogs.MaxDeleteBatch":                     false,
@@@ -90,6 -89,7 +90,7 @@@
        "Collections.PreserveVersionIfIdle":            true,
        "Collections.TrashSweepInterval":               false,
        "Collections.TrustAllContent":                  false,
+       "Collections.WebDAVCache":                      false,
        "Containers":                                   true,
        "Containers.CloudVMs":                          false,
        "Containers.CrunchRunCommand":                  false,
        "Containers.DefaultKeepCacheRAM":               true,
        "Containers.DispatchPrivateKey":                false,
        "Containers.JobsAPI":                           true,
-       "Containers.JobsAPI.CrunchJobUser":             false,
-       "Containers.JobsAPI.CrunchJobWrapper":          false,
-       "Containers.JobsAPI.CrunchRefreshTrigger":      false,
-       "Containers.JobsAPI.DefaultDockerImage":        false,
        "Containers.JobsAPI.Enable":                    true,
        "Containers.JobsAPI.GitInternalDir":            false,
-       "Containers.JobsAPI.ReuseJobIfOutputsDiffer":   false,
        "Containers.Logging":                           false,
        "Containers.LogReuseDecisions":                 false,
        "Containers.MaxComputeVMs":                     false,
index ffcdddfe2fce5962babde94f1a47853174b14a2c,6cb8bf81aee3607d6bce79986e466d0b86eb807e..1eae24d84e540ccc597cc0dcf8f048fadf19514e
@@@ -212,17 -212,14 +212,17 @@@ Clusters
        WebsocketClientEventQueue: 64
        WebsocketServerEventQueue: 4
  
 +      # Timeout on requests to internal Keep services.
 +      KeepServiceRequestTimeout: 15s
 +
      Users:
        # Config parameters to automatically setup new users.  If enabled,
        # this users will be able to self-activate.  Enable this if you want
        # to run an open instance where anyone can create an account and use
        # the system without requiring manual approval.
        #
-       # The params auto_setup_new_users_with_* are meaningful only when auto_setup_new_users is turned on.
-       # auto_setup_name_blacklist is a list of usernames to be blacklisted for auto setup.
+       # The params AutoSetupNewUsersWith* are meaningful only when AutoSetupNewUsers is turned on.
+       # AutoSetupUsernameBlacklist is a list of usernames to be blacklisted for auto setup.
        AutoSetupNewUsers: false
        AutoSetupNewUsersWithVmUUID: ""
        AutoSetupNewUsersWithRepository: false
          syslog: {}
          SAMPLE: {}
  
-       # When new_users_are_active is set to true, new users will be active
+       # When NewUsersAreActive is set to true, new users will be active
        # immediately.  This skips the "self-activate" step which enforces
        # user agreements.  Should only be enabled for development.
        NewUsersAreActive: false
        # should be an address associated with a Google account.
        AutoAdminUserWithEmail: ""
  
-       # If auto_admin_first_user is set to true, the first user to log in when no
+       # If AutoAdminFirstUser is set to true, the first user to log in when no
        # other admin users exist will automatically become an admin user.
        AutoAdminFirstUser: false
  
        NewUserNotificationRecipients: {}
        NewInactiveUserNotificationRecipients: {}
  
-       # Set anonymous_user_token to enable anonymous user access. You can get
+       # Set AnonymousUserToken to enable anonymous user access. You can get
        # the token by running "bundle exec ./script/get_anonymous_user_token.rb"
        # in the directory where your API server is running.
        AnonymousUserToken: ""
  
        # Maximum number of log rows to delete in a single SQL transaction.
        #
-       # If max_audit_log_delete_batch is 0, log entries will never be
+       # If MaxDeleteBatch is 0, log entries will never be
        # deleted by Arvados. Cleanup can be done by an external process
        # without affecting any Arvados system processes, as long as very
        # recent (<5 minutes old) logs are not deleted.
        # identical to the permission key given to Keep. IMPORTANT: This is
        # a site secret. It should be at least 50 characters.
        #
-       # Modifying blob_signing_key will invalidate all existing
+       # Modifying BlobSigningKey will invalidate all existing
        # signatures, which can cause programs to fail (e.g., arv-put,
        # arv-get, and Crunch jobs).  To avoid errors, rotate keys only when
        # no such processes are running.
        # keepstore servers.  Otherwise, reading data blocks and saving
        # collections will fail with HTTP 403 permission errors.
        #
-       # Modifying blob_signature_ttl invalidates existing signatures; see
-       # blob_signing_key note above.
+       # Modifying BlobSigningTTL invalidates existing signatures; see
+       # BlobSigningKey note above.
        #
        # The default is 2 weeks.
        BlobSigningTTL: 336h
  
        # Default lifetime for ephemeral collections: 2 weeks. This must not
-       # be less than blob_signature_ttl.
+       # be less than BlobSigningTTL.
        DefaultTrashLifetime: 336h
  
        # Interval (seconds) between trash sweeps. During a trash sweep,
  
        # If true, enable collection versioning.
        # When a collection's preserve_version field is true or the current version
-       # is older than the amount of seconds defined on preserve_version_if_idle,
+       # is older than the amount of seconds defined on PreserveVersionIfIdle,
        # a snapshot of the collection's previous state is created and linked to
        # the current collection.
        CollectionVersioning: false
        # The default setting (false) is appropriate for a multi-user site.
        TrustAllContent: false
  
+       # Cache parameters for WebDAV content serving:
+       # * TTL: Maximum time to cache manifests and permission checks.
+       # * UUIDTTL: Maximum time to cache collection state.
+       # * MaxBlockEntries: Maximum number of block cache entries.
+       # * MaxCollectionEntries: Maximum number of collection cache entries.
+       # * MaxCollectionBytes: Approximate memory limit for collection cache.
+       # * MaxPermissionEntries: Maximum number of permission cache entries.
+       # * MaxUUIDEntries: Maximum number of UUID cache entries.
+       WebDAVCache:
+         TTL: 300s
+         UUIDTTL: 5s
+         MaxBlockEntries:      4
+         MaxCollectionEntries: 1000
+         MaxCollectionBytes:   100000000
+         MaxPermissionEntries: 1000
+         MaxUUIDEntries:       1000
      Login:
        # These settings are provided by your OAuth2 provider (e.g.,
        # sso-provider).
            AssignNodeHostname: "compute%<slot_number>d"
  
        JobsAPI:
-         # Enable the legacy Jobs API.  This value must be a string.
+         # Enable the legacy 'jobs' API (crunch v1).  This value must be a string.
+         #
+         # Note: this only enables read-only access, creating new
+         # legacy jobs and pipelines is not supported.
+         #
          # 'auto' -- (default) enable the Jobs API only if it has been used before
          #         (i.e., there are job records in the database)
          # 'true' -- enable the Jobs API despite lack of existing records.
          # {git_repositories_dir}/arvados/.git
          GitInternalDir: /var/lib/arvados/internal.git
  
-         # Docker image to be used when none found in runtime_constraints of a job
-         DefaultDockerImage: ""
-         # none or slurm_immediate
-         CrunchJobWrapper: none
-         # username, or false = do not set uid when running jobs.
-         CrunchJobUser: crunch
-         # The web service must be able to create/write this file, and
-         # crunch-job must be able to stat() it.
-         CrunchRefreshTrigger: /tmp/crunch_refresh_trigger
-         # Control job reuse behavior when two completed jobs match the
-         # search criteria and have different outputs.
-         #
-         # If true, in case of a conflict, reuse the earliest job (this is
-         # similar to container reuse behavior).
-         #
-         # If false, in case of a conflict, do not reuse any completed job,
-         # but do reuse an already-running job if available (this is the
-         # original job reuse behavior, and is still the default).
-         ReuseJobIfOutputsDiffer: false
        CloudVMs:
          # Enable the cloud scheduler (experimental).
          Enable: false
diff --combined lib/config/load.go
index 309c0a615dc98620ac86895c471f60db5c50807c,3413e3bec3c0418098d39f10c984c20e25c48d69..c0b44c17eb3f421256ea8ca61b05ed965e45288b
@@@ -31,9 -31,9 +31,10 @@@ type Loader struct 
  
        Path                    string
        KeepstorePath           string
+       KeepWebPath             string
        CrunchDispatchSlurmPath string
        WebsocketPath           string
 +      KeepproxyPath           string
  
        configdata []byte
  }
@@@ -61,9 -61,9 +62,10 @@@ func NewLoader(stdin io.Reader, logger 
  func (ldr *Loader) SetupFlags(flagset *flag.FlagSet) {
        flagset.StringVar(&ldr.Path, "config", arvados.DefaultConfigFile, "Site configuration `file` (default may be overridden by setting an ARVADOS_CONFIG environment variable)")
        flagset.StringVar(&ldr.KeepstorePath, "legacy-keepstore-config", defaultKeepstoreConfigPath, "Legacy keepstore configuration `file`")
+       flagset.StringVar(&ldr.KeepWebPath, "legacy-keepweb-config", defaultKeepWebConfigPath, "Legacy keep-web configuration `file`")
        flagset.StringVar(&ldr.CrunchDispatchSlurmPath, "legacy-crunch-dispatch-slurm-config", defaultCrunchDispatchSlurmConfigPath, "Legacy crunch-dispatch-slurm configuration `file`")
        flagset.StringVar(&ldr.WebsocketPath, "legacy-ws-config", defaultWebsocketConfigPath, "Legacy arvados-ws configuration `file`")
 +      flagset.StringVar(&ldr.KeepproxyPath, "legacy-keepproxy-config", defaultKeepproxyConfigPath, "Legacy keepproxy configuration `file`")
        flagset.BoolVar(&ldr.SkipLegacy, "skip-legacy", false, "Don't load legacy config files")
  }
  
@@@ -135,9 -135,9 +137,12 @@@ func (ldr *Loader) MungeLegacyConfigArg
        if legacyConfigArg != "-legacy-ws-config" {
                ldr.WebsocketPath = ""
        }
+       if legacyConfigArg != "-legacy-keepweb-config" {
+               ldr.KeepWebPath = ""
+       }
 +      if legacyConfigArg != "-legacy-keepproxy-config" {
 +              ldr.WebsocketPath = ""
 +      }
  
        return munged
  }
@@@ -235,9 -235,9 +240,10 @@@ func (ldr *Loader) Load() (*arvados.Con
                // legacy config file for the current component
                for _, err := range []error{
                        ldr.loadOldKeepstoreConfig(&cfg),
+                       ldr.loadOldKeepWebConfig(&cfg),
                        ldr.loadOldCrunchDispatchSlurmConfig(&cfg),
                        ldr.loadOldWebsocketConfig(&cfg),
 +                      ldr.loadOldKeepproxyConfig(&cfg),
                } {
                        if err != nil {
                                return nil, err
diff --combined sdk/go/arvados/config.go
index bc434a20304bbbd129ed64d76307469c46a43fbc,02043fb6d192e63a0e438b9f12981efbd259df70..93f52f3c809bb003c3bb506574d42e140728960c
@@@ -57,6 -57,15 +57,15 @@@ func (sc *Config) GetCluster(clusterID 
        }
  }
  
+ type WebDAVCacheConfig struct {
+       TTL                  Duration
+       UUIDTTL              Duration
+       MaxBlockEntries      int
+       MaxCollectionEntries int
+       MaxCollectionBytes   int64
+       MaxPermissionEntries int
+       MaxUUIDEntries       int
+ }
  type Cluster struct {
        ClusterID       string `json:"-"`
        ManagementToken string
@@@ -79,7 -88,6 +88,7 @@@
                SendTimeout                    Duration
                WebsocketClientEventQueue      int
                WebsocketServerEventQueue      int
 +              KeepServiceRequestTimeout      Duration
        }
        AuditLogs struct {
                MaxAge             Duration
                PreserveVersionIfIdle Duration
                TrashSweepInterval    Duration
                TrustAllContent       bool
+               WebDAVCache WebDAVCacheConfig
        }
        Git struct {
                Repositories string
@@@ -272,13 -282,8 +283,8 @@@ type ContainersConfig struct 
        UsePreemptibleInstances     bool
  
        JobsAPI struct {
-               Enable                  string
-               GitInternalDir          string
-               DefaultDockerImage      string
-               CrunchJobWrapper        string
-               CrunchJobUser           string
-               CrunchRefreshTrigger    string
-               ReuseJobIfOutputsDiffer bool
+               Enable         string
+               GitInternalDir string
        }
        Logging struct {
                MaxAge                       Duration
index cde0cefb6e8aa23c723883100c054713eb671458,80227e6cd0a79335e7486beac156c72cde4b8d87..e79b4843a268049e117d60e59a37a8de62e61fbb
@@@ -544,11 -544,10 +544,11 @@@ def run_keep_proxy()
      env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
      logf = open(_logfilename('keepproxy'), 'a')
      kp = subprocess.Popen(
 -        ['keepproxy',
 -         '-pid='+_pidfile('keepproxy'),
 -         '-listen=:{}'.format(port)],
 -        env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
 +        ['keepproxy'], env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
 +
 +    with open(_pidfile('keepproxy'), 'w') as f:
 +        f.write(str(kp.pid))
 +    _wait_until_port_listens(port)
  
      print("Using API %s token %s" % (os.environ['ARVADOS_API_HOST'], auth_token('admin')), file=sys.stdout)
      api = arvados.api(
@@@ -605,14 -604,9 +605,9 @@@ def run_keep_web()
  
      keepwebport = internal_port_from_config("WebDAV")
      env = os.environ.copy()
-     env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
      logf = open(_logfilename('keep-web'), 'a')
      keepweb = subprocess.Popen(
-         ['keep-web',
-          '-allow-anonymous',
-          '-attachment-only-host=download',
-          '-management-token=e687950a23c3a9bceec28c6223a06c79',
-          '-listen=:'+str(keepwebport)],
+         ['keep-web'],
          env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
      with open(_pidfile('keep-web'), 'w') as f:
          f.write(str(keepweb.pid))
@@@ -746,7 -740,13 +741,13 @@@ def setup_config()
                  "TLS": {
                      "Insecure": True
                  },
-                 "Services": services
+                 "Services": services,
+                 "Users": {
+                     "AnonymousUserToken": auth_token('anonymous')
+                 },
+                 "Collections": {
+                     "TrustAllContent": True
+                 }
              }
          }
      }
index 3444e61e1728b166f6b04c37c5d55ee75940691f,58bedd2841b41e0a5cf2a6e1a0cc0a8158ab69f0..34a0c2d75221b0466c23870ead2a996b929987da
@@@ -70,34 -70,46 +70,50 @@@ Clusters
    ${uuid_prefix}:
      ManagementToken: $management_token
      Services:
+       RailsAPI:
+         InternalURLs:
+           "http://localhost:${services[api]}": {}
        Workbench1:
          ExternalURL: "https://$localip:${services[workbench]}"
        Workbench2:
          ExternalURL: "https://$localip:${services[workbench2-ssl]}"
        SSO:
          ExternalURL: "https://$localip:${services[sso]}"
 +      Keepproxy:
 +        InternalURLs:
 +          "http://localhost:${services[keepproxy]}/": {}
 +        ExternalURL: "http://$localip:${services[keepproxy-ssl]}/"
        Websocket:
          ExternalURL: "wss://$localip:${services[websockets-ssl]}/websocket"
+         InternalURLs:
+           "http://localhost:${services[websockets]}": {}
        GitSSH:
          ExternalURL: "ssh://git@$localip:"
        GitHTTP:
          ExternalURL: "http://$localip:${services[arv-git-httpd]}/"
        WebDAV:
+         InternalURLs:
+           "http://localhost:${services[keep-web]}/": {}
+         ExternalURL: "https://$localip:${services[keep-web-ssl]}/"
+       WebDAVDownload:
+         InternalURLs:
+           "http://localhost:${services[keep-web]}/": {}
          ExternalURL: "https://$localip:${services[keep-web-ssl]}/"
+         InternalURLs:
+           "http://localhost:${services[keep-web]}/": {}
        Composer:
          ExternalURL: "http://$localip:${services[composer]}"
        Controller:
          ExternalURL: "https://$localip:${services[controller-ssl]}"
-     NodeProfiles:  # to be deprecated in favor of "Services" section
-       "*":
-         arvados-controller:
-           Listen: ":${services[controller]}" # choose a port
-         arvados-api-server:
-           Listen: ":${services[api]}" # must match Rails server port in your Nginx config
+         InternalURLs:
+           "http://localhost:${services[controller]}": {}
+       RailsAPI:
+         InternalURLs:
+           "http://localhost:${services[api]}/": {}
+       Keepproxy:
+         ExternalURL: "https://$localip:${services[keepproxy-ssl]}"
+         InternalURLs:
+           "http://localhost:${services[keepproxy]}": {}
      PostgreSQL:
        ConnectionPool: 32 # max concurrent connections per arvados server daemon
        Connection:
      Collections:
        BlobSigningKey: $blob_signing_key
        DefaultReplication: 1
+       TrustAllContent: true
      Login:
        ProviderAppSecret: $sso_app_secret
        ProviderAppID: arvados-server
        AutoSetupNewUsers: true
        AutoSetupNewUsersWithVmUUID: $vm_uuid
        AutoSetupNewUsersWithRepository: true
+       AnonymousUserToken: $(cat /var/lib/arvados/superuser_token)
      Workbench:
        SecretKeyBase: $workbench_secret_key_base
        ArvadosDocsite: http://$localip:${services[doc]}/
index 55c647d5ba0ebe2f7b9db0f3554f4d9dade74da6,78b5bcf8e8d430d302b4922c10b241c9469512f9..96457a6e5931a6dffa0378a09333b2c4edd53698
@@@ -25,8 -25,8 +25,8 @@@ set +
  read -rd $'\000' keepservice <<EOF
  {
   "service_host":"$localip",
-  "service_port":${services[keepproxy]},
-  "service_ssl_flag":false,
+  "service_port":${services[keepproxy-ssl]},
+  "service_ssl_flag":true,
   "service_type":"proxy"
  }
  EOF
@@@ -40,4 -40,4 +40,4 @@@ els
      echo $UUID > /var/lib/arvados/keepproxy-uuid
  fi
  
 -exec /usr/local/bin/keepproxy -listen=:${services[keepproxy]}
 +exec /usr/local/bin/keepproxy