diff --git a/src/common/proc.c b/src/common/proc.c index 703658afd45..79bcf7c01bf 100644 --- a/src/common/proc.c +++ b/src/common/proc.c @@ -1,5 +1,6 @@ /** * (C) Copyright 2019-2022 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -69,6 +70,63 @@ crt_proc_struct_daos_acl(crt_proc_t proc, crt_proc_op_t proc_op, return rc; } +static int +crt_proc_struct_daos_prop_byteval(crt_proc_t proc, crt_proc_op_t proc_op, + struct daos_prop_byteval **data, uint32_t type) +{ + struct daos_prop_byteval *bv; + uint64_t len = 0; + int rc; + + if (proc == NULL || data == NULL) + return -DER_INVAL; + + if (FREEING(proc_op)) { + bv = *data; + if (bv != NULL) { + D_FREE(bv->dpb_data); + D_FREE(bv); + *data = NULL; + } + return 0; + } + + if (ENCODING(proc_op) && *data != NULL) + len = (*data)->dpb_len; + + rc = crt_proc_uint64_t(proc, proc_op, &len); + if (rc) + return rc; + + if (len > DAOS_PROP_BYTEVAL_MAX_LEN) { + D_ERROR("byteval prop %u len " DF_U64 " exceeds max %u\n", type, len, + DAOS_PROP_BYTEVAL_MAX_LEN); + return -DER_INVAL; + } + + if (DECODING(proc_op)) { + if (len == 0) { + *data = NULL; + return 0; + } + D_ALLOC_PTR(bv); + if (bv == NULL) + return -DER_NOMEM; + D_ALLOC(bv->dpb_data, len); + if (bv->dpb_data == NULL) { + D_FREE(bv); + return -DER_NOMEM; + } + bv->dpb_len = len; + *data = bv; + } + + if (len > 0) + rc = crt_proc_memcpy(proc, proc_op, (*data)->dpb_data, len); + + return rc; +} + static int crt_proc_prop_entries(crt_proc_t proc, crt_proc_op_t proc_op, daos_prop_t *prop) { @@ -106,6 +164,10 @@ crt_proc_prop_entries(crt_proc_t proc, crt_proc_op_t proc_op, daos_prop_t *prop) } else if (entry->dpe_type == DAOS_PROP_PO_SVC_LIST) { rc = crt_proc_d_rank_list_t(proc, proc_op, (d_rank_list_t **)&entry->dpe_val_ptr); + } else if (daos_prop_has_byteval(entry)) { + rc = crt_proc_struct_daos_prop_byteval( + proc, proc_op, (struct daos_prop_byteval **)&entry->dpe_val_ptr, + entry->dpe_type); } else if (entry->dpe_type == DAOS_PROP_CO_ROOTS) { struct daos_prop_co_roots *roots; diff --git a/src/common/prop.c b/src/common/prop.c index cdbe4dd1b7f..1cf3b215eaf 100644 --- a/src/common/prop.c +++ b/src/common/prop.c @@ -81,12 +81,11 @@ bool daos_prop_has_byteval(struct daos_prop_entry *entry) { switch (entry->dpe_type) { - /* - * e.g. DAOS_PROP_PO_POOL_CA (DAOS-18783) - */ - default: - return false; + case DAOS_PROP_PO_POOL_CA: + case DAOS_PROP_PO_CERT_WATERMARKS: + return true; } + return false; } static void @@ -329,6 +328,9 @@ daos_prop_valid(daos_prop_t *prop, bool pool, bool input) /* for output parameter need not check entry value */ if (!input) continue; + /* Byteval payload semantics are validated at the trust boundary above. */ + if (daos_prop_has_byteval(&prop->dpp_entries[i])) + continue; switch (type) { /* pool properties */ case DAOS_PROP_PO_LABEL: @@ -800,6 +802,11 @@ daos_prop_entry_set_byteval(struct daos_prop_entry *entry, const void *data, siz D_ERROR("Entry type %d does not expect a byteval\n", entry->dpe_type); return -DER_INVAL; } + if (len > DAOS_PROP_BYTEVAL_MAX_LEN) { + D_ERROR("byteval prop %d len %zu exceeds max %u\n", entry->dpe_type, len, + DAOS_PROP_BYTEVAL_MAX_LEN); + return -DER_INVAL; + } if (entry->dpe_val_ptr != NULL) { bv = entry->dpe_val_ptr; @@ -970,6 +977,10 @@ daos_prop_copy(daos_prop_t *prop_req, daos_prop_t *prop_reply) D_GOTO(out, rc); roots_alloc = true; + } else if (daos_prop_has_byteval(entry_reply)) { + rc = daos_prop_entry_copy(entry_reply, entry_req); + if (rc) + D_GOTO(out, rc); } else { entry_req->dpe_val = entry_reply->dpe_val; } @@ -1098,6 +1109,28 @@ daos_prop_entry_cmp_acl(struct daos_prop_entry *entry1, return 0; } +int +daos_prop_entry_cmp_byteval(struct daos_prop_entry *entry1, struct daos_prop_entry *entry2) +{ + struct daos_prop_byteval *bv1 = entry1->dpe_val_ptr; + struct daos_prop_byteval *bv2 = entry2->dpe_val_ptr; + size_t len1 = (bv1 == NULL) ? 0 : bv1->dpb_len; + size_t len2 = (bv2 == NULL) ? 0 : bv2->dpb_len; + + D_ASSERT(daos_prop_has_byteval(entry1)); + D_ASSERT(daos_prop_has_byteval(entry2)); + + if (len1 != len2) { + D_ERROR("byteval prop %u len mismatch: %zu != %zu\n", entry1->dpe_type, len1, len2); + return -DER_MISMATCH; + } + if (len1 > 0 && memcmp(bv1->dpb_data, bv2->dpb_data, len1) != 0) { + D_ERROR("byteval prop %u content mismatch\n", entry1->dpe_type); + return -DER_MISMATCH; + } + return 0; +} + static int parse_entry(char *str, struct daos_prop_entry *entry) { diff --git a/src/common/tests/prop_tests.c b/src/common/tests/prop_tests.c index 0c2c51f5c72..e11343969d4 100644 --- a/src/common/tests/prop_tests.c +++ b/src/common/tests/prop_tests.c @@ -1,6 +1,6 @@ /* * (C) Copyright 2020-2022 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -491,6 +491,157 @@ test_daos_prop_valid_cont_success_no_val_check(void **state) daos_prop_free(prop); } +static void +test_daos_prop_has_byteval_types(void **state) +{ + struct daos_prop_entry entry = {0}; + + entry.dpe_type = DAOS_PROP_PO_POOL_CA; + assert_true(daos_prop_has_byteval(&entry)); + + entry.dpe_type = DAOS_PROP_PO_LABEL; + assert_false(daos_prop_has_byteval(&entry)); +} + +static void +test_daos_prop_byteval_set_round_trip(void **state) +{ + const uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03}; + daos_prop_t *prop; + struct daos_prop_entry *entry; + struct daos_prop_byteval *bv; + + prop = daos_prop_alloc(1); + assert_non_null(prop); + prop->dpp_entries[0].dpe_type = DAOS_PROP_PO_POOL_CA; + + assert_rc_equal(daos_prop_set_byteval(prop, DAOS_PROP_PO_POOL_CA, payload, sizeof(payload)), + 0); + + entry = daos_prop_entry_get(prop, DAOS_PROP_PO_POOL_CA); + assert_non_null(entry); + bv = entry->dpe_val_ptr; + assert_non_null(bv); + assert_int_equal(bv->dpb_len, sizeof(payload)); + assert_memory_equal(bv->dpb_data, payload, sizeof(payload)); + + daos_prop_free(prop); +} + +static void +test_daos_prop_byteval_oversize_rejected(void **state) +{ + struct daos_prop_entry entry = {0}; + uint8_t *blob; + size_t oversize; + int rc; + + entry.dpe_type = DAOS_PROP_PO_POOL_CA; + + oversize = (size_t)DAOS_PROP_BYTEVAL_MAX_LEN + 1; + D_ALLOC(blob, 16); + assert_non_null(blob); + + rc = daos_prop_entry_set_byteval(&entry, blob, oversize); + assert_rc_equal(rc, -DER_INVAL); + assert_null(entry.dpe_val_ptr); + + D_FREE(blob); +} + +static void +test_daos_prop_byteval_dup_preserves_value(void **state) +{ + const uint8_t payload[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + daos_prop_t *src; + daos_prop_t *dst; + struct daos_prop_entry *src_entry; + struct daos_prop_entry *dst_entry; + struct daos_prop_byteval *src_bv; + struct daos_prop_byteval *dst_bv; + + src = daos_prop_alloc(1); + assert_non_null(src); + src->dpp_entries[0].dpe_type = DAOS_PROP_PO_CERT_WATERMARKS; + assert_rc_equal( + daos_prop_set_byteval(src, DAOS_PROP_PO_CERT_WATERMARKS, payload, sizeof(payload)), 0); + + dst = daos_prop_dup(src, true /* pool */, false /* input */); + assert_non_null(dst); + + src_entry = daos_prop_entry_get(src, DAOS_PROP_PO_CERT_WATERMARKS); + dst_entry = daos_prop_entry_get(dst, DAOS_PROP_PO_CERT_WATERMARKS); + assert_non_null(src_entry); + assert_non_null(dst_entry); + + src_bv = src_entry->dpe_val_ptr; + dst_bv = dst_entry->dpe_val_ptr; + assert_non_null(dst_bv); + assert_ptr_not_equal(src_bv, dst_bv); + assert_int_equal(dst_bv->dpb_len, sizeof(payload)); + assert_memory_equal(dst_bv->dpb_data, payload, sizeof(payload)); + + daos_prop_free(src); + daos_prop_free(dst); +} + +/* Empty byteval (NULL ptr / zero len) must round-trip through dup as NULL, + * not as -DER_NOMEM from a zero-size allocation. + */ +static void +test_daos_prop_byteval_empty_dup(void **state) +{ + daos_prop_t *src; + daos_prop_t *dst; + struct daos_prop_entry *dst_entry; + + src = daos_prop_alloc(1); + assert_non_null(src); + src->dpp_entries[0].dpe_type = DAOS_PROP_PO_POOL_CA; + src->dpp_entries[0].dpe_val_ptr = NULL; + + dst = daos_prop_dup(src, true /* pool */, false /* input */); + assert_non_null(dst); + + dst_entry = daos_prop_entry_get(dst, DAOS_PROP_PO_POOL_CA); + assert_non_null(dst_entry); + assert_null(dst_entry->dpe_val_ptr); + + daos_prop_free(src); + daos_prop_free(dst); +} + +static void +test_daos_prop_byteval_cmp(void **state) +{ + const uint8_t a[] = {0x01, 0x02, 0x03, 0x04}; + const uint8_t b[] = {0x01, 0x02, 0x03, 0x05}; /* differs in last byte */ + struct daos_prop_entry e1 = {.dpe_type = DAOS_PROP_PO_POOL_CA}; + struct daos_prop_entry e2 = {.dpe_type = DAOS_PROP_PO_POOL_CA}; + + /* both NULL -> match */ + assert_rc_equal(daos_prop_entry_cmp_byteval(&e1, &e2), 0); + + /* NULL vs populated -> mismatch */ + assert_rc_equal(daos_prop_entry_set_byteval(&e1, a, sizeof(a)), 0); + assert_rc_equal(daos_prop_entry_cmp_byteval(&e1, &e2), -DER_MISMATCH); + + /* equal payloads -> match */ + assert_rc_equal(daos_prop_entry_set_byteval(&e2, a, sizeof(a)), 0); + assert_rc_equal(daos_prop_entry_cmp_byteval(&e1, &e2), 0); + + /* different content, same length -> mismatch */ + assert_rc_equal(daos_prop_entry_set_byteval(&e2, b, sizeof(b)), 0); + assert_rc_equal(daos_prop_entry_cmp_byteval(&e1, &e2), -DER_MISMATCH); + + /* different length -> mismatch */ + assert_rc_equal(daos_prop_entry_set_byteval(&e2, a, sizeof(a) - 1), 0); + assert_rc_equal(daos_prop_entry_cmp_byteval(&e1, &e2), -DER_MISMATCH); + + daos_prop_entry_set_byteval(&e1, NULL, 0); + daos_prop_entry_set_byteval(&e2, NULL, 0); +} + static int suite_setup(void **state) { @@ -521,6 +672,12 @@ main(void) cmocka_unit_test(test_daos_prop_valid_duplicate_types), cmocka_unit_test(test_daos_prop_valid_pool_success_no_val_check), cmocka_unit_test(test_daos_prop_valid_cont_success_no_val_check), + cmocka_unit_test(test_daos_prop_has_byteval_types), + cmocka_unit_test(test_daos_prop_byteval_set_round_trip), + cmocka_unit_test(test_daos_prop_byteval_oversize_rejected), + cmocka_unit_test(test_daos_prop_byteval_dup_preserves_value), + cmocka_unit_test(test_daos_prop_byteval_empty_dup), + cmocka_unit_test(test_daos_prop_byteval_cmp), }; return cmocka_run_group_tests_name("common_prop", tests, suite_setup, suite_teardown); diff --git a/src/control/cmd/daos_agent/config.go b/src/control/cmd/daos_agent/config.go index 418ffadfefe..35b4229ae46 100644 --- a/src/control/cmd/daos_agent/config.go +++ b/src/control/cmd/daos_agent/config.go @@ -1,6 +1,7 @@ // // (C) Copyright 2020-2024 Intel Corporation. // (C) Copyright 2025 Google LLC +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -11,6 +12,7 @@ import ( "fmt" "io" "os" + "path/filepath" "regexp" "time" @@ -28,6 +30,10 @@ const ( defaultRuntimeDir = "/var/run/daos_agent" ) +func defaultNodeCertDir(systemName string) string { + return filepath.Join("/etc/daos/certs", systemName, "node_certs") +} + type refreshMinutes time.Duration func (rm *refreshMinutes) UnmarshalYAML(unmarshal func(interface{}) error) error { @@ -137,6 +143,7 @@ type Config struct { FabricInterfaces []*NUMAFabricConfig `yaml:"fabric_ifaces,omitempty"` ProviderIdx uint // TODO SRS-31: Enable with multiprovider functionality Telemetry TelemetryConfig `yaml:",inline"` + NodeCertDir string `yaml:"node_cert_dir,omitempty"` } // Validate performs basic validation of the configuration. @@ -157,6 +164,10 @@ func (c *Config) Validate() error { return err } + if c.NodeCertDir == "" { + c.NodeCertDir = defaultNodeCertDir(c.SystemName) + } + return nil } diff --git a/src/control/cmd/daos_agent/config_test.go b/src/control/cmd/daos_agent/config_test.go index 69f50152605..233730e6882 100644 --- a/src/control/cmd/daos_agent/config_test.go +++ b/src/control/cmd/daos_agent/config_test.go @@ -1,6 +1,7 @@ // // (C) Copyright 2021-2024 Intel Corporation. // (C) Copyright 2025 Google LLC +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -120,8 +121,12 @@ exclude_fabric_ifaces: ["ib3"] expErr: errors.New("yaml: unmarshal error"), }, "empty config file": { - path: emptyFile, - expResult: DefaultConfig(), + path: emptyFile, + expResult: func() *Config { + cfg := DefaultConfig() + cfg.NodeCertDir = defaultNodeCertDir(cfg.SystemName) + return cfg + }(), }, "without optional items": { path: withoutOptCfg, @@ -137,6 +142,7 @@ exclude_fabric_ifaces: ["ib3"] AllowInsecure: true, CertificateConfig: DefaultConfig().TransportConfig.CertificateConfig, }, + NodeCertDir: defaultNodeCertDir("shire"), }, }, "bad log mask": { @@ -173,6 +179,7 @@ exclude_fabric_ifaces: ["ib3"] AllowInsecure: true, CertificateConfig: DefaultConfig().TransportConfig.CertificateConfig, }, + NodeCertDir: defaultNodeCertDir("shire"), ExcludeFabricIfaces: common.NewStringSet("ib3"), FabricInterfaces: []*NUMAFabricConfig{ { @@ -221,6 +228,13 @@ exclude_fabric_ifaces: ["ib3"] } func TestAgent_ReadConfig(t *testing.T) { + // validatedDefault returns a DefaultConfig with NodeCertDir populated + // as Validate() would set it. + validatedDefault := func() *Config { + cfg := DefaultConfig() + cfg.NodeCertDir = defaultNodeCertDir(cfg.SystemName) + return cfg + } cfgWith := func(cfg *Config, xfrm func(*Config) *Config) *Config { if xfrm != nil { cfg = xfrm(cfg) @@ -234,7 +248,7 @@ func TestAgent_ReadConfig(t *testing.T) { expErr error }{ "empty": { - expCfg: DefaultConfig(), + expCfg: validatedDefault(), }, "telemetry enabled with no port": { input: ` @@ -298,7 +312,7 @@ telemetry_retain: foo telemetry_port: 1234 telemetry_enabled: true `, - expCfg: cfgWith(DefaultConfig(), func(cfg *Config) *Config { + expCfg: cfgWith(validatedDefault(), func(cfg *Config) *Config { cfg.Telemetry.Port = 1234 cfg.Telemetry.Enabled = true return cfg @@ -310,7 +324,7 @@ telemetry_port: 1234 telemetry_enabled: true telemetry_retain: 10s `, - expCfg: cfgWith(DefaultConfig(), func(cfg *Config) *Config { + expCfg: cfgWith(validatedDefault(), func(cfg *Config) *Config { cfg.Telemetry.Port = 1234 cfg.Telemetry.Enabled = true cfg.Telemetry.Retain = 10 * time.Second @@ -323,7 +337,7 @@ telemetry_port: 1234 telemetry_enabled: true telemetry_enabled_procs: ^foo$ `, - expCfg: cfgWith(DefaultConfig(), func(cfg *Config) *Config { + expCfg: cfgWith(validatedDefault(), func(cfg *Config) *Config { cfg.Telemetry.Port = 1234 cfg.Telemetry.Enabled = true cfg.Telemetry.RegPattern = (*ConfigRegexp)(regexp.MustCompile("^foo$")) diff --git a/src/control/cmd/daos_agent/node_cert.go b/src/control/cmd/daos_agent/node_cert.go new file mode 100644 index 00000000000..8b403a50b95 --- /dev/null +++ b/src/control/cmd/daos_agent/node_cert.go @@ -0,0 +1,74 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package main + +import ( + "crypto/x509" + "fmt" + "strings" + "time" + + "github.com/google/uuid" + "github.com/pkg/errors" + + "github.com/daos-stack/daos/src/control/logging" + "github.com/daos-stack/daos/src/control/security" + "github.com/daos-stack/daos/src/control/security/auth" +) + +func validateNodeCertForUse(cert *x509.Certificate, poolID string, now time.Time) error { + cn := cert.Subject.CommonName + switch { + case strings.HasPrefix(cn, security.CertCNPrefixTenant): + case strings.HasPrefix(cn, security.CertCNPrefixNode): + // Must use the same source as AUTH_SYS machine_name; revoke-by-CN depends on it. + nodeName := strings.TrimPrefix(cn, security.CertCNPrefixNode) + machine, err := auth.GetMachineName() + if err != nil { + return errors.Wrap(err, "getting machine name for CN validation") + } + if nodeName != machine { + return fmt.Errorf("node cert CN %q does not match machine name %q (pool %s)", + cn, machine, poolID) + } + default: + return fmt.Errorf("node cert CN %q has no recognized prefix (pool %s)", cn, poolID) + } + + if now.After(cert.NotAfter) { + return fmt.Errorf("node certificate for pool %s expired at %s", + poolID, cert.NotAfter.Format(time.RFC3339)) + } + if now.Add(security.NotBeforeSkewTolerance).Before(cert.NotBefore) { + return fmt.Errorf("node certificate for pool %s not yet valid (notBefore=%s, local now=%s)", + poolID, cert.NotBefore.Format(time.RFC3339), + now.Format(time.RFC3339)) + } + return nil +} + +func getNodeCertAndPoP(log logging.Logger, loader *security.NodeCertLoader, poolID string, handleUUID []byte) (cert *security.NodeCert, certPEM, pop, payload []byte, err error) { + poolUUID, err := uuid.Parse(poolID) + if err != nil { + return nil, nil, nil, nil, errors.Wrap(err, "parsing pool UUID") + } + + cert, err = loader.Load(log, poolID) + if err != nil { + return nil, nil, nil, nil, err + } + if err := validateNodeCertForUse(cert.Cert, poolID, time.Now()); err != nil { + return nil, nil, nil, nil, err + } + + payload = security.BuildPoPPayload(poolUUID, handleUUID) + pop, err = security.SignPoP(cert.Key, cert.Cert, payload) + if err != nil { + return nil, nil, nil, nil, errors.Wrap(err, "signing PoP") + } + return cert, cert.PEM, pop, payload, nil +} diff --git a/src/control/cmd/daos_agent/node_cert_test.go b/src/control/cmd/daos_agent/node_cert_test.go new file mode 100644 index 00000000000..6ed285e47dd --- /dev/null +++ b/src/control/cmd/daos_agent/node_cert_test.go @@ -0,0 +1,149 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package main + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "os" + "path/filepath" + "testing" + "time" + + "github.com/google/uuid" + + "github.com/daos-stack/daos/src/control/common/test" + "github.com/daos-stack/daos/src/control/logging" + "github.com/daos-stack/daos/src/control/security" + "github.com/daos-stack/daos/src/control/security/auth" +) + +func writeNodeCertForCN(t *testing.T, dir, poolUUID, cn string, notBefore, notAfter time.Time) { + t.Helper() + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageDigitalSignature, + } + certDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, poolUUID+".crt"), + pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}), 0644); err != nil { + t.Fatal(err) + } + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, poolUUID+".key"), + pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), 0400); err != nil { + t.Fatal(err) + } +} + +func TestAgent_ValidateNodeCertForUse(t *testing.T) { + machine, err := auth.GetMachineName() + if err != nil { + t.Fatal(err) + } + now := time.Now() + notBefore := now.Add(-time.Minute) + notAfter := now.Add(time.Hour) + + cases := map[string]struct { + cn string + notBefore time.Time + notAfter time.Time + now time.Time + expectErr bool + }{ + "node cert matches machine": {security.CertCNPrefixNode + machine, notBefore, notAfter, now, false}, + "node cert wrong machine": {security.CertCNPrefixNode + "wronghost", notBefore, notAfter, now, true}, + "tenant cert skips machine": {security.CertCNPrefixTenant + "team-a", notBefore, notAfter, now, false}, + "unrecognized prefix": {"weird:thing", notBefore, notAfter, now, true}, + "expired cert": {security.CertCNPrefixNode + machine, notBefore, now.Add(-time.Minute), now, true}, + "not yet valid": {security.CertCNPrefixNode + machine, now.Add(time.Hour), notAfter, now, true}, + "not yet valid within skew": {security.CertCNPrefixNode + machine, now.Add(time.Minute), notAfter, now, false}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + cert := &x509.Certificate{ + Subject: pkix.Name{CommonName: tc.cn}, + NotBefore: tc.notBefore, + NotAfter: tc.notAfter, + } + err := validateNodeCertForUse(cert, "12345678-1234-1234-1234-123456789abc", tc.now) + if tc.expectErr && err == nil { + t.Fatal("expected error, got nil") + } + if !tc.expectErr && err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + } +} + +func TestAgent_GetNodeCertAndPoP(t *testing.T) { + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + machine, err := auth.GetMachineName() + if err != nil { + t.Fatal(err) + } + poolUUID := "12345678-1234-1234-1234-123456789abc" + handleUUID := uuid.MustParse("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee") + writeNodeCertForCN(t, tmpDir, poolUUID, security.CertCNPrefixNode+machine, + time.Now().Add(-time.Minute), time.Now().Add(time.Hour)) + + log, _ := logging.NewTestLogger(t.Name()) + loader := security.NewNodeCertLoader(tmpDir) + _, certPEM, pop, payload, err := getNodeCertAndPoP(log, loader, poolUUID, handleUUID[:]) + if err != nil { + t.Fatalf("getNodeCertAndPoP failed: %v", err) + } + if len(certPEM) == 0 || len(pop) == 0 { + t.Fatal("expected non-empty certPEM and pop") + } + if len(payload) != security.PoPPayloadLen { + t.Fatalf("expected %d byte payload, got %d", security.PoPPayloadLen, len(payload)) + } +} + +func TestAgent_GetNodeCertAndPoP_BadPoolUUID(t *testing.T) { + log, _ := logging.NewTestLogger(t.Name()) + loader := security.NewNodeCertLoader("/tmp") + if _, _, _, _, err := getNodeCertAndPoP(log, loader, "not-a-uuid", nil); err == nil { + t.Fatal("expected error for invalid pool UUID") + } +} + +func TestAgent_GetNodeCertAndPoP_MissingCert(t *testing.T) { + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + log, _ := logging.NewTestLogger(t.Name()) + loader := security.NewNodeCertLoader(tmpDir) + poolUUID := "99999999-9999-9999-9999-999999999999" + if _, _, _, _, err := getNodeCertAndPoP(log, loader, poolUUID, nil); err == nil { + t.Fatal("expected error for missing cert") + } +} diff --git a/src/control/cmd/daos_agent/security_rpc.go b/src/control/cmd/daos_agent/security_rpc.go index f75bf1ecef2..75a0f9b815c 100644 --- a/src/control/cmd/daos_agent/security_rpc.go +++ b/src/control/cmd/daos_agent/security_rpc.go @@ -1,6 +1,6 @@ // // (C) Copyright 2018-2024 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -15,6 +15,7 @@ import ( "time" "github.com/pkg/errors" + "google.golang.org/protobuf/proto" "github.com/daos-stack/daos/src/control/drpc" "github.com/daos-stack/daos/src/control/lib/cache" @@ -46,8 +47,9 @@ type ( // securityConfig defines configuration parameters for SecurityModule. securityConfig struct { - credentials *security.CredentialConfig - transport *security.TransportConfig + credentials *security.CredentialConfig + transport *security.TransportConfig + nodeCertLoader *security.NodeCertLoader } // SecurityModule is the security drpc module struct @@ -165,12 +167,20 @@ func (m *SecurityModule) HandleCall(ctx context.Context, session *drpc.Session, return nil, drpc.UnknownMethodFailure() } - return m.getCredential(ctx, session) + var req auth.GetCredReq + if len(body) > 0 { + if err := proto.Unmarshal(body, &req); err != nil { + m.log.Errorf("failed to unmarshal GetCredReq: %s", err) + // Fall through with empty req for backward compat + } + } + + return m.getCredential(ctx, session, req.GetPoolId(), req.GetHandleUuid()) } -// getCredentials generates a signed user credential based on the data attached to -// the Unix Domain Socket. -func (m *SecurityModule) getCredential(ctx context.Context, session *drpc.Session) ([]byte, error) { +// getCredential generates a signed user credential from the Unix Domain +// Socket peer data. When poolID is set, also signs a per-pool node cert PoP. +func (m *SecurityModule) getCredential(ctx context.Context, session *drpc.Session, poolID string, handleUUID []byte) ([]byte, error) { if session == nil { return nil, drpc.NewFailureWithMessage("session is nil") } @@ -220,6 +230,22 @@ func (m *SecurityModule) getCredential(ctx context.Context, session *drpc.Sessio } resp := &auth.GetCredResp{Cred: cred} + + if poolID != "" && m.config.nodeCertLoader != nil { + cert, certPEM, pop, payload, err := getNodeCertAndPoP(m.log, m.config.nodeCertLoader, poolID, handleUUID) + if err != nil { + // Log but don't fail — server decides if cert is required + m.log.Tracef("no node cert for pool %s: %s", poolID, err) + } else { + m.log.Tracef("attaching node cert for pool %s (CN=%s, expires=%s, %d bytes PoP)", + poolID, cert.Cert.Subject.CommonName, + cert.Cert.NotAfter.Format("2006-01-02"), len(pop)) + resp.NodeCert = certPEM + resp.NodeCertPop = pop + resp.NodeCertPayload = payload + } + } + return drpc.Marshal(resp) } diff --git a/src/control/cmd/daos_agent/start.go b/src/control/cmd/daos_agent/start.go index c5f6f519630..5cb4959c36a 100644 --- a/src/control/cmd/daos_agent/start.go +++ b/src/control/cmd/daos_agent/start.go @@ -1,6 +1,7 @@ // // (C) Copyright 2020-2024 Intel Corporation. // (C) Copyright 2025 Google LLC +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -25,6 +26,7 @@ import ( "github.com/daos-stack/daos/src/control/lib/hardware/hwloc" "github.com/daos-stack/daos/src/control/lib/systemd" "github.com/daos-stack/daos/src/control/lib/telemetry/promexp" + "github.com/daos-stack/daos/src/control/security" ) type ctxKey string @@ -108,8 +110,9 @@ func (cmd *startCmd) Execute(_ []string) error { drpcRegStart := time.Now() secCfg := &securityConfig{ - transport: cmd.cfg.TransportConfig, - credentials: cmd.cfg.CredentialConfig, + transport: cmd.cfg.TransportConfig, + credentials: cmd.cfg.CredentialConfig, + nodeCertLoader: security.NewNodeCertLoader(cmd.cfg.NodeCertDir), } drpcServer.RegisterRPCModule(NewSecurityModule(cmd.Logger, secCfg)) mgmtMod := &mgmtModule{ diff --git a/src/control/cmd/dmg/command_test.go b/src/control/cmd/dmg/command_test.go index 4e8bc07a2d6..ea3602c20c3 100644 --- a/src/control/cmd/dmg/command_test.go +++ b/src/control/cmd/dmg/command_test.go @@ -1,7 +1,7 @@ // // (C) Copyright 2019-2024 Intel Corporation. // (C) Copyright 2025 Google LLC -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -17,6 +17,7 @@ import ( "regexp" "strings" "testing" + "time" "github.com/google/go-cmp/cmp" "gopkg.in/yaml.v2" @@ -176,6 +177,18 @@ func (bci *bridgeConnInvoker) InvokeUnaryRPC(ctx context.Context, uReq control.U case *control.PoolGetACLReq, *control.PoolOverwriteACLReq, *control.PoolUpdateACLReq, *control.PoolDeleteACLReq: resp = control.MockMSResponse("", nil, &mgmtpb.ACLResp{}) + case *control.PoolGetCAReq: + resp = control.MockMSResponse("", nil, &mgmtpb.PoolGetCAResp{}) + case *control.PoolAddCAReq: + resp = control.MockMSResponse("", nil, &mgmtpb.PoolAddCAResp{}) + case *control.PoolRemoveCAReq: + resp = control.MockMSResponse("", nil, &mgmtpb.PoolRemoveCAResp{}) + case *control.PoolGetCertWatermarksReq: + resp = control.MockMSResponse("", nil, &mgmtpb.PoolGetCertWatermarksResp{}) + case *control.PoolRevokeClientReq: + resp = control.MockMSResponse("", nil, &mgmtpb.PoolRevokeClientResp{ + WatermarkRfc3339: time.Now().UTC().Format(time.RFC3339), + }) case *control.PoolRanksReq: resp = control.MockMSResponse("", nil, &mgmtpb.PoolRanksResp{}) case *control.PoolExtendReq: diff --git a/src/control/cmd/dmg/json_test.go b/src/control/cmd/dmg/json_test.go index b3993c309bc..217ac7f3143 100644 --- a/src/control/cmd/dmg/json_test.go +++ b/src/control/cmd/dmg/json_test.go @@ -1,6 +1,6 @@ // // (C) Copyright 2020-2024 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -12,6 +12,7 @@ import ( "encoding/json" "io" "os" + "path/filepath" "reflect" "strings" "testing" @@ -19,6 +20,7 @@ import ( "github.com/daos-stack/daos/src/control/common/test" "github.com/daos-stack/daos/src/control/lib/control" "github.com/daos-stack/daos/src/control/logging" + sectest "github.com/daos-stack/daos/src/control/security/test" ) func walkStruct(v reflect.Value, prefix []string, visit func([]string)) { @@ -63,6 +65,8 @@ func TestDmg_JsonOutput(t *testing.T) { aclContent := "A::OWNER@:rw\nA::user1@:rw\nA:g:group1@:r\n" aclPath := test.CreateTestFile(t, testDir, aclContent) + caKeyPath, caCertPath := sectest.WriteCAFiles(t, testDir) + for _, args := range cmdArgs { t.Run(strings.Join(args, " "), func(t *testing.T) { testArgs := append([]string{"-i", "--json"}, args...) @@ -70,6 +74,14 @@ func TestDmg_JsonOutput(t *testing.T) { case "version", "telemetry config", "telemetry run", "config generate", "manpage", "system set-prop", "support collect-log", "check repair": return + case "pool set-cert": + testArgs = append(testArgs, test.MockUUID(), + "--cert", caCertPath) + case "pool add-client": + testArgs = append(testArgs, test.MockUUID(), + "--pool-ca-key", caKeyPath, + "--node", "testnode", + "--output", filepath.Join(testDir, "client_certs")) case "storage nvme-rebind": testArgs = append(testArgs, "-l", "foo.com", "-a", test.MockPCIAddr()) @@ -87,8 +99,16 @@ func TestDmg_JsonOutput(t *testing.T) { case "pool create": testArgs = append(testArgs, "-s", "1TB", "label") case "pool destroy", "pool evict", "pool query", "pool get-acl", "pool upgrade", - "pool rebuild start", "pool rebuild stop": + "pool rebuild start", "pool rebuild stop", + "pool get-cert", "pool list-revocations": testArgs = append(testArgs, test.MockUUID()) + case "pool delete-cert": + testArgs = append(testArgs, test.MockUUID(), "--all") + case "pool revoke-client": + testArgs = append(testArgs, test.MockUUID(), + "--pool-ca-key", caKeyPath, + "--node", "testnode", + "--output", filepath.Join(testDir, "revoked_certs")) case "pool overwrite-acl", "pool update-acl": testArgs = append(testArgs, test.MockUUID(), "-a", aclPath) case "pool delete-acl": diff --git a/src/control/cmd/dmg/pool.go b/src/control/cmd/dmg/pool.go index 1c5d42dacaa..a3933cd2536 100644 --- a/src/control/cmd/dmg/pool.go +++ b/src/control/cmd/dmg/pool.go @@ -32,24 +32,30 @@ import ( // PoolCmd is the struct representing the top-level pool subcommand. type PoolCmd struct { - Create poolCreateCmd `command:"create" description:"Create a DAOS pool"` - Destroy poolDestroyCmd `command:"destroy" description:"Destroy a DAOS pool"` - Evict poolEvictCmd `command:"evict" description:"Evict all pool connections to a DAOS pool"` - List poolListCmd `command:"list" alias:"ls" description:"List DAOS pools"` - Extend poolExtendCmd `command:"extend" description:"Extend a DAOS pool to include new ranks"` - Exclude poolExcludeCmd `command:"exclude" description:"Exclude targets from a set of ranks"` - Drain poolDrainCmd `command:"drain" description:"Drain targets from a set of ranks"` - Reintegrate poolReintegrateCmd `command:"reintegrate" alias:"reint" description:"Reintegrate targets for a set of rank"` - Query poolQueryCmd `command:"query" description:"Query a DAOS pool"` - QueryTargets poolQueryTargetsCmd `command:"query-targets" description:"Query pool target info"` - GetACL poolGetACLCmd `command:"get-acl" description:"Get a DAOS pool's Access Control List"` - OverwriteACL poolOverwriteACLCmd `command:"overwrite-acl" description:"Overwrite a DAOS pool's Access Control List"` - UpdateACL poolUpdateACLCmd `command:"update-acl" description:"Update entries in a DAOS pool's Access Control List"` - DeleteACL poolDeleteACLCmd `command:"delete-acl" description:"Delete an entry from a DAOS pool's Access Control List"` - SetProp poolSetPropCmd `command:"set-prop" description:"Set pool property"` - GetProp poolGetPropCmd `command:"get-prop" description:"Get pool properties"` - Upgrade poolUpgradeCmd `command:"upgrade" description:"Upgrade pool to latest format"` - Rebuild poolRebuildCmd `command:"rebuild" description:"Manage interactive rebuild process for pools"` + Create poolCreateCmd `command:"create" description:"Create a DAOS pool"` + Destroy poolDestroyCmd `command:"destroy" description:"Destroy a DAOS pool"` + Evict poolEvictCmd `command:"evict" description:"Evict all pool connections to a DAOS pool"` + List poolListCmd `command:"list" alias:"ls" description:"List DAOS pools"` + Extend poolExtendCmd `command:"extend" description:"Extend a DAOS pool to include new ranks"` + Exclude poolExcludeCmd `command:"exclude" description:"Exclude targets from a set of ranks"` + Drain poolDrainCmd `command:"drain" description:"Drain targets from a set of ranks"` + Reintegrate poolReintegrateCmd `command:"reintegrate" alias:"reint" description:"Reintegrate targets for a set of rank"` + Query poolQueryCmd `command:"query" description:"Query a DAOS pool"` + QueryTargets poolQueryTargetsCmd `command:"query-targets" description:"Query pool target info"` + GetACL poolGetACLCmd `command:"get-acl" description:"Get a DAOS pool's Access Control List"` + OverwriteACL poolOverwriteACLCmd `command:"overwrite-acl" description:"Overwrite a DAOS pool's Access Control List"` + UpdateACL poolUpdateACLCmd `command:"update-acl" description:"Update entries in a DAOS pool's Access Control List"` + DeleteACL poolDeleteACLCmd `command:"delete-acl" description:"Delete an entry from a DAOS pool's Access Control List"` + SetProp poolSetPropCmd `command:"set-prop" description:"Set pool property"` + GetProp poolGetPropCmd `command:"get-prop" description:"Get pool properties"` + Upgrade poolUpgradeCmd `command:"upgrade" description:"Upgrade pool to latest format"` + Rebuild poolRebuildCmd `command:"rebuild" description:"Manage interactive rebuild process for pools"` + SetCert poolSetCertCmd `command:"set-cert" description:"Set pool node certificate CA"` + GetCert poolGetCertCmd `command:"get-cert" description:"Get pool node certificate CA info"` + DeleteCert poolDeleteCertCmd `command:"delete-cert" description:"Remove pool node certificate requirement"` + AddClient poolAddClientCmd `command:"add-client" description:"Generate client certificate for pool access"` + RevokeClient poolRevokeClientCmd `command:"revoke-client" description:"Revoke a node or tenant and issue a replacement certificate"` + ListRevocations poolListRevocationsCmd `command:"list-revocations" description:"List per-CN revocation watermarks on the pool"` } var ( diff --git a/src/control/cmd/dmg/pool_cert.go b/src/control/cmd/dmg/pool_cert.go new file mode 100644 index 00000000000..9918cf0e7fd --- /dev/null +++ b/src/control/cmd/dmg/pool_cert.go @@ -0,0 +1,422 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package main + +import ( + "fmt" + "os" + "path/filepath" + "sort" + "time" + + "github.com/pkg/errors" + + "github.com/daos-stack/daos/src/control/lib/control" + "github.com/daos-stack/daos/src/control/security" +) + +// writeFileOverwrite writes data to path, removing any existing file first +// (needed when the existing file has restrictive permissions like 0400). +func writeFileOverwrite(path string, data []byte, perm os.FileMode) error { + os.Remove(path) + return os.WriteFile(path, data, perm) +} + +// poolSetCertCmd sets a pool-specific intermediate CA certificate. +type poolSetCertCmd struct { + poolCmd + CAKey string `long:"daos-ca-key" description:"Path to DAOS CA private key"` + Output string `long:"output" short:"o" description:"Output directory for pool CA key pair"` + Cert string `long:"cert" description:"Path to pre-existing pool CA certificate (import mode)"` + Replace bool `long:"replace" description:"Replace any existing CA bundle on the pool"` + Append bool `long:"append" description:"Append to an existing CA bundle on the pool"` +} + +func (cmd *poolSetCertCmd) Execute(args []string) error { + if cmd.Replace && cmd.Append { + return errors.New("--replace and --append are mutually exclusive") + } + + if !cmd.Replace && !cmd.Append { + // Refuse implicit append/replace when the pool already has CAs. + existing, err := control.PoolGetCA(cmd.MustLogCtx(), cmd.ctlInvoker, + &control.PoolGetCAReq{ID: cmd.PoolID().String()}) + if err == nil && existing != nil && len(existing.Certs) > 0 { + return errors.Errorf("pool already has %d CA(s) installed; specify --replace or --append", + len(existing.Certs)) + } + } + + req := &control.PoolSetupCertAuthReq{ + ID: cmd.PoolID().String(), + Replace: cmd.Replace, + } + + if cmd.Cert != "" { + // Import mode + if cmd.CAKey != "" || cmd.Output != "" { + return errors.New("--cert is mutually exclusive with --daos-ca-key and --output") + } + + certPEM, err := os.ReadFile(cmd.Cert) + if err != nil { + return errors.Wrap(err, "reading pool CA certificate") + } + + req.CertPEM = certPEM + // Chain validation requires the DAOS CA cert on disk. + // Skip when running insecure (no certs available). + if cmd.config == nil || cmd.config.TransportConfig == nil || + !cmd.config.TransportConfig.AllowInsecure { + req.DaosCACertPath = cmd.getDaosCACertPath() + } + } else { + // Generate mode + if cmd.CAKey == "" || cmd.Output == "" { + return errors.New("--daos-ca-key and --output are required (or use --cert for import mode)") + } + + req.DaosCACertPath = cmd.getDaosCACertPath() + req.DaosCAKeyPath = cmd.CAKey + } + + resp, err := control.PoolSetupCertAuth(cmd.MustLogCtx(), cmd.ctlInvoker, req) + // Persist the returned CA key pair before the JSON return so --output works + // in both --json and text modes. Mirrors poolAddClientCmd/poolRevokeClientCmd. + if err == nil && cmd.Output != "" && len(resp.CAKeyPEM) > 0 { + if mkErr := os.MkdirAll(cmd.Output, 0750); mkErr != nil { + return errors.Wrap(mkErr, "creating output directory") + } + uuid := resp.PoolUUID + certPath := filepath.Join(cmd.Output, uuid+"_ca.crt") + if wErr := writeFileOverwrite(certPath, resp.CACertPEM, 0644); wErr != nil { + return errors.Wrap(wErr, "writing pool CA certificate") + } + keyPath := filepath.Join(cmd.Output, uuid+"_ca.key") + if wErr := writeFileOverwrite(keyPath, resp.CAKeyPEM, 0400); wErr != nil { + return errors.Wrap(wErr, "writing pool CA key") + } + cmd.Infof("Pool CA written to %s and %s", certPath, keyPath) + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(resp, err) + } + if err != nil { + return err + } + + cmd.Infof("Pool CA set successfully") + return nil +} + +// getDaosCACertPath returns the DAOS CA cert path from transport config, +// falling back to the default path. +func (cmd *poolSetCertCmd) getDaosCACertPath() string { + if cmd.config != nil && cmd.config.TransportConfig != nil && + cmd.config.TransportConfig.CARootPath != "" { + return cmd.config.TransportConfig.CARootPath + } + return security.DefaultCACertPath +} + +// poolGetCertCmd displays the pool's node certificate CA info. +type poolGetCertCmd struct { + poolCmd +} + +func (cmd *poolGetCertCmd) Execute(args []string) error { + resp, err := control.PoolGetCA(cmd.MustLogCtx(), cmd.ctlInvoker, + &control.PoolGetCAReq{ID: cmd.PoolID().String()}) + + type getCertResult struct { + Certificates []security.PoolCertInfo `json:"certificates"` + } + var result getCertResult + if err == nil && resp != nil { + result.Certificates = resp.Certs + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(result, err) + } + if err != nil { + return errors.Wrap(err, "getting pool CA") + } + + if len(result.Certificates) == 0 { + cmd.Infof("No pool CA configured") + return nil + } + + for i, ci := range result.Certificates { + cmd.Infof("Pool CA Certificate [%d]:", i) + cmd.Infof(" Subject: %s", ci.Subject) + cmd.Infof(" Issuer: %s", ci.Issuer) + cmd.Infof(" Not Before: %s", ci.NotBefore) + cmd.Infof(" Not After: %s", ci.NotAfter) + cmd.Infof(" Fingerprint: %s", ci.Fingerprint) + } + + return nil +} + +// poolDeleteCertCmd removes CA(s) from the pool's CA bundle. +type poolDeleteCertCmd struct { + poolCmd + Fingerprint string `long:"fingerprint" description:"SHA-256 fingerprint of CA to remove (hex)"` + All bool `long:"all" description:"Remove all CAs (disables node auth)"` +} + +func (cmd *poolDeleteCertCmd) Execute(args []string) error { + if !cmd.All && cmd.Fingerprint == "" { + return errors.New("specify --fingerprint to remove a specific CA, or --all to remove all") + } + + req := &control.PoolRemoveCAReq{ + ID: cmd.PoolID().String(), + } + if cmd.All { + req.All = true + } else { + req.Fingerprint = cmd.Fingerprint + } + + resp, err := control.PoolRemoveCA(cmd.MustLogCtx(), cmd.ctlInvoker, req) + if err != nil { + return err + } + + type deleteCertResult struct { + CertsRemoved int `json:"certs_removed"` + Status string `json:"status"` + } + result := deleteCertResult{CertsRemoved: resp.CertsRemoved} + if cmd.All { + result.Status = "All pool CAs removed; node auth disabled" + } else { + result.Status = fmt.Sprintf("Removed %d CA(s) from bundle", resp.CertsRemoved) + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(result, nil) + } + + cmd.Infof("%s", result.Status) + return nil +} + +// poolAddClientCmd generates certificates signed by a pool's CA. +// Either --node or --tenant must be specified, but not both. +type poolAddClientCmd struct { + poolCmd + CAKey string `long:"pool-ca-key" required:"1" description:"Path to pool CA private key"` + Nodes []string `long:"node" description:"Node name(s) to generate certs for"` + Tenants []string `long:"tenant" description:"Tenant name(s) to generate certs for"` + Output string `long:"output" short:"o" required:"1" description:"Output directory"` +} + +func (cmd *poolAddClientCmd) Execute(args []string) error { + if len(cmd.Nodes) == 0 && len(cmd.Tenants) == 0 { + return errors.New("specify --node or --tenant") + } + if len(cmd.Nodes) > 0 && len(cmd.Tenants) > 0 { + return errors.New("--node and --tenant are mutually exclusive") + } + + poolResp, err := control.PoolQuery(cmd.MustLogCtx(), cmd.ctlInvoker, + &control.PoolQueryReq{ID: cmd.PoolID().String()}) + if err != nil { + return errors.Wrap(err, "resolving pool UUID") + } + poolUUID := poolResp.UUID.String() + + certs, err := control.PoolGenerateClientCerts( + &control.PoolGenerateClientCertsReq{ + CAKeyPath: cmd.CAKey, + Nodes: cmd.Nodes, + Tenants: cmd.Tenants, + }) + if err != nil { + return err + } + + // 0700 because this directory holds private keys. + if err := os.MkdirAll(cmd.Output, 0700); err != nil { + return errors.Wrap(err, "creating output directory") + } + + type clientCertResult struct { + CN string `json:"cn"` + CertPath string `json:"cert_path"` + KeyPath string `json:"key_path"` + } + var results []clientCertResult + + for _, c := range certs { + outDir := filepath.Join(cmd.Output, c.Name) + if err := os.MkdirAll(outDir, 0700); err != nil { + return errors.Wrapf(err, "creating directory for %s", c.CN) + } + + r := clientCertResult{CN: c.CN} + r.CertPath = filepath.Join(outDir, poolUUID+".crt") + if err := writeFileOverwrite(r.CertPath, c.CertPEM, 0644); err != nil { + return errors.Wrapf(err, "writing cert for %s", c.CN) + } + r.KeyPath = filepath.Join(outDir, poolUUID+".key") + if err := writeFileOverwrite(r.KeyPath, c.KeyPEM, 0400); err != nil { + return errors.Wrapf(err, "writing key for %s", c.CN) + } + results = append(results, r) + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(results, nil) + } + + for _, r := range results { + cmd.Infof(" %s: %s, %s", r.CN, r.CertPath, r.KeyPath) + } + kind := "node" + count := len(cmd.Nodes) + if len(cmd.Tenants) > 0 { + kind = "tenant" + count = len(cmd.Tenants) + } + cmd.Infof("Certificates generated for %d %s(s)", count, kind) + return nil +} + +// poolRevokeClientCmd advances the pool's revocation watermark for a CN +// and writes a fresh replacement cert+key for that identity. +type poolRevokeClientCmd struct { + poolCmd + CAKey string `long:"pool-ca-key" required:"1" description:"Path to pool CA private key"` + Node string `long:"node" description:"Node name to revoke"` + Tenant string `long:"tenant" description:"Tenant name to revoke"` + Output string `long:"output" short:"o" required:"1" description:"Output directory for the replacement cert"` + EvictAllHandles bool `long:"evict-all-handles" description:"Evict every active pool handle (default for tenant: revocations)"` + NoEvict bool `long:"no-evict" description:"Advance the watermark but leave active handles alive"` +} + +func (cmd *poolRevokeClientCmd) Execute(args []string) error { + if cmd.Node == "" && cmd.Tenant == "" { + return errors.New("specify --node or --tenant") + } + if cmd.Node != "" && cmd.Tenant != "" { + return errors.New("--node and --tenant are mutually exclusive") + } + if cmd.EvictAllHandles && cmd.NoEvict { + return errors.New("--evict-all-handles and --no-evict are mutually exclusive") + } + + evictMode := control.PoolRevokeEvictDefault + switch { + case cmd.EvictAllHandles: + evictMode = control.PoolRevokeEvictPoolWide + case cmd.NoEvict: + evictMode = control.PoolRevokeEvictNone + } + + resp, err := control.PoolRevokeClient(cmd.MustLogCtx(), cmd.ctlInvoker, + &control.PoolRevokeClientReq{ + ID: cmd.PoolID().String(), + CAKeyPath: cmd.CAKey, + Node: cmd.Node, + Tenant: cmd.Tenant, + EvictMode: evictMode, + }) + if err != nil { + return errors.Wrap(err, "revoking client") + } + + type revokeResult struct { + CN string `json:"cn"` + CertPath string `json:"cert_path"` + KeyPath string `json:"key_path"` + Watermark string `json:"watermark"` + HandlesEvicted int32 `json:"handles_evicted"` + EvictScope string `json:"evict_scope"` + } + result := revokeResult{ + CN: resp.Cert.CN, + Watermark: resp.Watermark.Format(time.RFC3339), + HandlesEvicted: resp.HandlesEvicted, + EvictScope: resp.EvictScope, + } + + outDir := filepath.Join(cmd.Output, resp.Cert.Name) + if err := os.MkdirAll(outDir, 0700); err != nil { + return errors.Wrapf(err, "creating output directory for %s", resp.Cert.CN) + } + + result.CertPath = filepath.Join(outDir, resp.PoolUUID+".crt") + if err := writeFileOverwrite(result.CertPath, resp.Cert.CertPEM, 0644); err != nil { + return errors.Wrapf(err, "writing cert for %s", resp.Cert.CN) + } + result.KeyPath = filepath.Join(outDir, resp.PoolUUID+".key") + if err := writeFileOverwrite(result.KeyPath, resp.Cert.KeyPEM, 0400); err != nil { + return errors.Wrapf(err, "writing key for %s", resp.Cert.CN) + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(result, nil) + } + + cmd.Infof("Revoked %s", resp.Cert.CN) + cmd.Infof(" Watermark: %s", result.Watermark) + cmd.Infof(" Replacement: %s, %s", result.CertPath, result.KeyPath) + cmd.Infof(" Handles evicted: %d (%s)", result.HandlesEvicted, result.EvictScope) + if result.EvictScope == "machine" && result.HandlesEvicted == 0 { + cmd.Noticef("No active handles matched %s — verify the CN is correct (the client may legitimately not have an active connection).", + resp.Cert.CN) + } + return nil +} + +// poolListRevocationsCmd lists the per-CN revocation watermarks set on a pool. +type poolListRevocationsCmd struct { + poolCmd +} + +func (cmd *poolListRevocationsCmd) Execute(args []string) error { + entries, err := control.PoolGetCertWatermarks(cmd.MustLogCtx(), cmd.ctlInvoker, + &control.PoolGetCertWatermarksReq{ID: cmd.PoolID().String()}) + if err != nil { + return errors.Wrap(err, "reading cert watermarks") + } + + type listRevocationsResult struct { + Revocations map[string]string `json:"revocations"` + } + result := listRevocationsResult{Revocations: make(map[string]string, len(entries))} + for cn, wm := range entries { + result.Revocations[cn] = wm.Format(time.RFC3339) + } + + if cmd.JSONOutputEnabled() { + return cmd.OutputJSON(result, nil) + } + + if len(entries) == 0 { + cmd.Infof("No revocations set on this pool") + return nil + } + + cns := make([]string, 0, len(entries)) + for cn := range entries { + cns = append(cns, cn) + } + sort.Strings(cns) + + cmd.Infof("Revocations:") + for _, cn := range cns { + cmd.Infof(" %s %s", cn, entries[cn].Format(time.RFC3339)) + } + return nil +} diff --git a/src/control/common/proto/mgmt/mgmt.pb.go b/src/control/common/proto/mgmt/mgmt.pb.go index 5c5d3c0c005..e3761facf12 100644 --- a/src/control/common/proto/mgmt/mgmt.pb.go +++ b/src/control/common/proto/mgmt/mgmt.pb.go @@ -43,8 +43,8 @@ var file_mgmt_mgmt_proto_rawDesc = []byte{ 0x2f, 0x61, 0x63, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0d, 0x63, 0x68, 0x6b, 0x2f, 0x63, 0x68, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x10, 0x63, 0x68, - 0x6b, 0x2f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xe5, - 0x18, 0x0a, 0x07, 0x4d, 0x67, 0x6d, 0x74, 0x53, 0x76, 0x63, 0x12, 0x27, 0x0a, 0x04, 0x4a, 0x6f, + 0x6b, 0x2f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xbf, + 0x1b, 0x0a, 0x07, 0x4d, 0x67, 0x6d, 0x74, 0x53, 0x76, 0x63, 0x12, 0x27, 0x0a, 0x04, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, @@ -97,243 +97,275 @@ var file_mgmt_mgmt_proto_rawDesc = []byte{ 0x74, 0x50, 0x72, 0x6f, 0x70, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x0a, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x41, - 0x43, 0x4c, 0x12, 0x0f, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x43, 0x4c, - 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x65, - 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x41, 0x43, 0x4c, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x09, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, + 0x41, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, + 0x43, 0x41, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, + 0x6c, 0x47, 0x65, 0x74, 0x43, 0x41, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x09, + 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x64, 0x43, 0x41, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x64, 0x43, 0x41, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x64, 0x43, 0x41, 0x52, 0x65, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0c, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x41, 0x12, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x41, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x41, 0x52, + 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x15, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, + 0x43, 0x65, 0x72, 0x74, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x12, 0x1e, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, + 0x74, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1f, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, + 0x74, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x1a, 0x1a, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x2e, + 0x0a, 0x0a, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x41, 0x43, 0x4c, 0x12, 0x0f, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, + 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x41, + 0x43, 0x4c, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, + 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x41, 0x43, + 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x0d, 0x50, 0x6f, 0x6f, 0x6c, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x43, 0x4c, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x34, 0x0a, - 0x0d, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x43, 0x4c, 0x12, 0x12, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x41, 0x43, 0x4c, 0x52, + 0x0d, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x43, 0x4c, 0x12, 0x12, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x0d, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x41, 0x43, 0x4c, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x43, 0x4c, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x41, 0x43, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b, 0x50, 0x6f, 0x6f, - 0x6c, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0e, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, - 0x12, 0x3f, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, - 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, - 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x12, 0x3d, 0x0a, 0x0f, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x53, 0x74, 0x6f, 0x70, 0x12, 0x18, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, - 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x0e, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, - 0x12, 0x3f, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, 0x61, 0x6c, - 0x45, 0x76, 0x61, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, - 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x1a, - 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, - 0x61, 0x63, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, - 0x6c, 0x73, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, - 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, 0x0a, - 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, - 0x11, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, - 0x53, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, - 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, - 0x39, 0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x13, 0x2e, - 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x6f, 0x70, 0x52, - 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, - 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, - 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, - 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, - 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, - 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x44, 0x72, 0x61, 0x69, 0x6e, 0x12, 0x14, 0x2e, 0x6d, 0x67, + 0x70, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x70, 0x67, 0x72, 0x61, + 0x64, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x70, + 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, + 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x10, 0x50, 0x6f, + 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x19, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0f, 0x50, + 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x18, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, + 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x10, 0x50, 0x6f, + 0x6f, 0x6c, 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x12, 0x19, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, + 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x47, + 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, + 0x36, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x12, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x1a, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6f, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x11, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x12, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x53, 0x65, + 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0a, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x78, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x44, 0x72, 0x61, 0x69, 0x6e, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x44, 0x72, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x44, 0x72, 0x61, 0x69, 0x6e, 0x52, 0x65, - 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x44, - 0x72, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x13, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x12, 0x1c, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, - 0x1d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, - 0x12, 0x43, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, - 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x12, 0x1b, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x13, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x6c, 0x66, 0x48, 0x65, 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, - 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, - 0x72, 0x61, 0x73, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x45, 0x72, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, - 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x11, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x2e, 0x6d, - 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x12, 0x1b, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, + 0x6c, 0x66, 0x48, 0x65, 0x61, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, + 0x3c, 0x0a, 0x0b, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x61, 0x73, 0x65, 0x12, 0x14, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x72, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, + 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x16, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x00, 0x12, 0x3b, 0x0a, 0x11, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, + 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x12, 0x15, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, + 0x10, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x12, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, + 0x0a, 0x0f, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x6f, + 0x70, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, + 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x10, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x12, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x41, 0x0a, + 0x14, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0e, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, + 0x12, 0x4b, 0x0a, 0x14, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x47, + 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, + 0x71, 0x1a, 0x18, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x47, 0x65, + 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, + 0x11, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x61, + 0x69, 0x72, 0x12, 0x11, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x41, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x17, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, + 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0d, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x15, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, + 0x74, 0x41, 0x74, 0x74, 0x72, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x10, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, - 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0f, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x67, - 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, - 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x10, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x13, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x67, - 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x14, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x6d, 0x67, - 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x14, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x47, 0x65, 0x74, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x11, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x70, 0x61, 0x69, 0x72, 0x12, 0x11, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x6d, 0x67, - 0x6d, 0x74, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x12, 0x4c, 0x0a, 0x17, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, - 0x39, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, - 0x74, 0x41, 0x74, 0x74, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x12, 0x16, 0x2e, 0x6d, 0x67, - 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, - 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x39, - 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x12, - 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x74, - 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, - 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, - 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, - 0x11, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x10, 0x2e, 0x63, 0x68, 0x6b, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x14, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, - 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x0a, - 0x2e, 0x63, 0x68, 0x6b, 0x2e, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x18, - 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x67, 0x6d, 0x74, 0x50, + 0x70, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x6f, 0x70, 0x12, 0x16, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x11, 0x46, 0x61, 0x75, 0x6c, 0x74, + 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x10, 0x2e, 0x63, + 0x68, 0x6b, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x0e, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, + 0x12, 0x34, 0x0a, 0x14, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x0a, 0x2e, 0x63, 0x68, 0x6b, 0x2e, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x1a, 0x0e, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, - 0x64, 0x61, 0x6f, 0x73, 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x67, - 0x6d, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x18, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x49, + 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x67, 0x6d, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x46, 0x61, 0x75, + 0x6c, 0x74, 0x12, 0x0a, 0x2e, 0x63, 0x68, 0x6b, 0x2e, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x1a, 0x0e, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x44, 0x61, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, + 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, + 0x61, 0x6f, 0x73, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2f, 0x73, + 0x72, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var file_mgmt_mgmt_proto_goTypes = []interface{}{ - (*JoinReq)(nil), // 0: mgmt.JoinReq - (*shared.ClusterEventReq)(nil), // 1: shared.ClusterEventReq - (*LeaderQueryReq)(nil), // 2: mgmt.LeaderQueryReq - (*PoolCreateReq)(nil), // 3: mgmt.PoolCreateReq - (*PoolDestroyReq)(nil), // 4: mgmt.PoolDestroyReq - (*PoolEvictReq)(nil), // 5: mgmt.PoolEvictReq - (*PoolExcludeReq)(nil), // 6: mgmt.PoolExcludeReq - (*PoolDrainReq)(nil), // 7: mgmt.PoolDrainReq - (*PoolExtendReq)(nil), // 8: mgmt.PoolExtendReq - (*PoolReintReq)(nil), // 9: mgmt.PoolReintReq - (*PoolQueryReq)(nil), // 10: mgmt.PoolQueryReq - (*PoolQueryTargetReq)(nil), // 11: mgmt.PoolQueryTargetReq - (*PoolSetPropReq)(nil), // 12: mgmt.PoolSetPropReq - (*PoolGetPropReq)(nil), // 13: mgmt.PoolGetPropReq - (*GetACLReq)(nil), // 14: mgmt.GetACLReq - (*ModifyACLReq)(nil), // 15: mgmt.ModifyACLReq - (*DeleteACLReq)(nil), // 16: mgmt.DeleteACLReq - (*PoolUpgradeReq)(nil), // 17: mgmt.PoolUpgradeReq - (*PoolRebuildStartReq)(nil), // 18: mgmt.PoolRebuildStartReq - (*PoolRebuildStopReq)(nil), // 19: mgmt.PoolRebuildStopReq - (*PoolSelfHealEvalReq)(nil), // 20: mgmt.PoolSelfHealEvalReq - (*GetAttachInfoReq)(nil), // 21: mgmt.GetAttachInfoReq - (*ListPoolsReq)(nil), // 22: mgmt.ListPoolsReq - (*ListContReq)(nil), // 23: mgmt.ListContReq - (*ContSetOwnerReq)(nil), // 24: mgmt.ContSetOwnerReq - (*SystemQueryReq)(nil), // 25: mgmt.SystemQueryReq - (*SystemStopReq)(nil), // 26: mgmt.SystemStopReq - (*SystemStartReq)(nil), // 27: mgmt.SystemStartReq - (*SystemExcludeReq)(nil), // 28: mgmt.SystemExcludeReq - (*SystemDrainReq)(nil), // 29: mgmt.SystemDrainReq - (*SystemRebuildManageReq)(nil), // 30: mgmt.SystemRebuildManageReq - (*SystemSelfHealEvalReq)(nil), // 31: mgmt.SystemSelfHealEvalReq - (*SystemEraseReq)(nil), // 32: mgmt.SystemEraseReq - (*SystemCleanupReq)(nil), // 33: mgmt.SystemCleanupReq - (*CheckEnableReq)(nil), // 34: mgmt.CheckEnableReq - (*CheckDisableReq)(nil), // 35: mgmt.CheckDisableReq - (*CheckStartReq)(nil), // 36: mgmt.CheckStartReq - (*CheckStopReq)(nil), // 37: mgmt.CheckStopReq - (*CheckQueryReq)(nil), // 38: mgmt.CheckQueryReq - (*CheckSetPolicyReq)(nil), // 39: mgmt.CheckSetPolicyReq - (*CheckGetPolicyReq)(nil), // 40: mgmt.CheckGetPolicyReq - (*CheckActReq)(nil), // 41: mgmt.CheckActReq - (*shared.CheckReportReq)(nil), // 42: shared.CheckReportReq - (*SystemSetAttrReq)(nil), // 43: mgmt.SystemSetAttrReq - (*SystemGetAttrReq)(nil), // 44: mgmt.SystemGetAttrReq - (*SystemSetPropReq)(nil), // 45: mgmt.SystemSetPropReq - (*SystemGetPropReq)(nil), // 46: mgmt.SystemGetPropReq - (*chk.CheckReport)(nil), // 47: chk.CheckReport - (*chk.Fault)(nil), // 48: chk.Fault - (*JoinResp)(nil), // 49: mgmt.JoinResp - (*shared.ClusterEventResp)(nil), // 50: shared.ClusterEventResp - (*LeaderQueryResp)(nil), // 51: mgmt.LeaderQueryResp - (*PoolCreateResp)(nil), // 52: mgmt.PoolCreateResp - (*PoolDestroyResp)(nil), // 53: mgmt.PoolDestroyResp - (*PoolEvictResp)(nil), // 54: mgmt.PoolEvictResp - (*PoolExcludeResp)(nil), // 55: mgmt.PoolExcludeResp - (*PoolDrainResp)(nil), // 56: mgmt.PoolDrainResp - (*PoolExtendResp)(nil), // 57: mgmt.PoolExtendResp - (*PoolReintResp)(nil), // 58: mgmt.PoolReintResp - (*PoolQueryResp)(nil), // 59: mgmt.PoolQueryResp - (*PoolQueryTargetResp)(nil), // 60: mgmt.PoolQueryTargetResp - (*PoolSetPropResp)(nil), // 61: mgmt.PoolSetPropResp - (*PoolGetPropResp)(nil), // 62: mgmt.PoolGetPropResp - (*ACLResp)(nil), // 63: mgmt.ACLResp - (*DaosResp)(nil), // 64: mgmt.DaosResp - (*GetAttachInfoResp)(nil), // 65: mgmt.GetAttachInfoResp - (*ListPoolsResp)(nil), // 66: mgmt.ListPoolsResp - (*ListContResp)(nil), // 67: mgmt.ListContResp - (*SystemQueryResp)(nil), // 68: mgmt.SystemQueryResp - (*SystemStopResp)(nil), // 69: mgmt.SystemStopResp - (*SystemStartResp)(nil), // 70: mgmt.SystemStartResp - (*SystemExcludeResp)(nil), // 71: mgmt.SystemExcludeResp - (*SystemDrainResp)(nil), // 72: mgmt.SystemDrainResp - (*SystemRebuildManageResp)(nil), // 73: mgmt.SystemRebuildManageResp - (*SystemEraseResp)(nil), // 74: mgmt.SystemEraseResp - (*SystemCleanupResp)(nil), // 75: mgmt.SystemCleanupResp - (*CheckStartResp)(nil), // 76: mgmt.CheckStartResp - (*CheckStopResp)(nil), // 77: mgmt.CheckStopResp - (*CheckQueryResp)(nil), // 78: mgmt.CheckQueryResp - (*CheckGetPolicyResp)(nil), // 79: mgmt.CheckGetPolicyResp - (*CheckActResp)(nil), // 80: mgmt.CheckActResp - (*shared.CheckReportResp)(nil), // 81: shared.CheckReportResp - (*SystemGetAttrResp)(nil), // 82: mgmt.SystemGetAttrResp - (*SystemGetPropResp)(nil), // 83: mgmt.SystemGetPropResp + (*JoinReq)(nil), // 0: mgmt.JoinReq + (*shared.ClusterEventReq)(nil), // 1: shared.ClusterEventReq + (*LeaderQueryReq)(nil), // 2: mgmt.LeaderQueryReq + (*PoolCreateReq)(nil), // 3: mgmt.PoolCreateReq + (*PoolDestroyReq)(nil), // 4: mgmt.PoolDestroyReq + (*PoolEvictReq)(nil), // 5: mgmt.PoolEvictReq + (*PoolExcludeReq)(nil), // 6: mgmt.PoolExcludeReq + (*PoolDrainReq)(nil), // 7: mgmt.PoolDrainReq + (*PoolExtendReq)(nil), // 8: mgmt.PoolExtendReq + (*PoolReintReq)(nil), // 9: mgmt.PoolReintReq + (*PoolQueryReq)(nil), // 10: mgmt.PoolQueryReq + (*PoolQueryTargetReq)(nil), // 11: mgmt.PoolQueryTargetReq + (*PoolSetPropReq)(nil), // 12: mgmt.PoolSetPropReq + (*PoolGetPropReq)(nil), // 13: mgmt.PoolGetPropReq + (*PoolGetCAReq)(nil), // 14: mgmt.PoolGetCAReq + (*PoolAddCAReq)(nil), // 15: mgmt.PoolAddCAReq + (*PoolRemoveCAReq)(nil), // 16: mgmt.PoolRemoveCAReq + (*PoolGetCertWatermarksReq)(nil), // 17: mgmt.PoolGetCertWatermarksReq + (*PoolRevokeClientReq)(nil), // 18: mgmt.PoolRevokeClientReq + (*GetACLReq)(nil), // 19: mgmt.GetACLReq + (*ModifyACLReq)(nil), // 20: mgmt.ModifyACLReq + (*DeleteACLReq)(nil), // 21: mgmt.DeleteACLReq + (*PoolUpgradeReq)(nil), // 22: mgmt.PoolUpgradeReq + (*PoolRebuildStartReq)(nil), // 23: mgmt.PoolRebuildStartReq + (*PoolRebuildStopReq)(nil), // 24: mgmt.PoolRebuildStopReq + (*PoolSelfHealEvalReq)(nil), // 25: mgmt.PoolSelfHealEvalReq + (*GetAttachInfoReq)(nil), // 26: mgmt.GetAttachInfoReq + (*ListPoolsReq)(nil), // 27: mgmt.ListPoolsReq + (*ListContReq)(nil), // 28: mgmt.ListContReq + (*ContSetOwnerReq)(nil), // 29: mgmt.ContSetOwnerReq + (*SystemQueryReq)(nil), // 30: mgmt.SystemQueryReq + (*SystemStopReq)(nil), // 31: mgmt.SystemStopReq + (*SystemStartReq)(nil), // 32: mgmt.SystemStartReq + (*SystemExcludeReq)(nil), // 33: mgmt.SystemExcludeReq + (*SystemDrainReq)(nil), // 34: mgmt.SystemDrainReq + (*SystemRebuildManageReq)(nil), // 35: mgmt.SystemRebuildManageReq + (*SystemSelfHealEvalReq)(nil), // 36: mgmt.SystemSelfHealEvalReq + (*SystemEraseReq)(nil), // 37: mgmt.SystemEraseReq + (*SystemCleanupReq)(nil), // 38: mgmt.SystemCleanupReq + (*CheckEnableReq)(nil), // 39: mgmt.CheckEnableReq + (*CheckDisableReq)(nil), // 40: mgmt.CheckDisableReq + (*CheckStartReq)(nil), // 41: mgmt.CheckStartReq + (*CheckStopReq)(nil), // 42: mgmt.CheckStopReq + (*CheckQueryReq)(nil), // 43: mgmt.CheckQueryReq + (*CheckSetPolicyReq)(nil), // 44: mgmt.CheckSetPolicyReq + (*CheckGetPolicyReq)(nil), // 45: mgmt.CheckGetPolicyReq + (*CheckActReq)(nil), // 46: mgmt.CheckActReq + (*shared.CheckReportReq)(nil), // 47: shared.CheckReportReq + (*SystemSetAttrReq)(nil), // 48: mgmt.SystemSetAttrReq + (*SystemGetAttrReq)(nil), // 49: mgmt.SystemGetAttrReq + (*SystemSetPropReq)(nil), // 50: mgmt.SystemSetPropReq + (*SystemGetPropReq)(nil), // 51: mgmt.SystemGetPropReq + (*chk.CheckReport)(nil), // 52: chk.CheckReport + (*chk.Fault)(nil), // 53: chk.Fault + (*JoinResp)(nil), // 54: mgmt.JoinResp + (*shared.ClusterEventResp)(nil), // 55: shared.ClusterEventResp + (*LeaderQueryResp)(nil), // 56: mgmt.LeaderQueryResp + (*PoolCreateResp)(nil), // 57: mgmt.PoolCreateResp + (*PoolDestroyResp)(nil), // 58: mgmt.PoolDestroyResp + (*PoolEvictResp)(nil), // 59: mgmt.PoolEvictResp + (*PoolExcludeResp)(nil), // 60: mgmt.PoolExcludeResp + (*PoolDrainResp)(nil), // 61: mgmt.PoolDrainResp + (*PoolExtendResp)(nil), // 62: mgmt.PoolExtendResp + (*PoolReintResp)(nil), // 63: mgmt.PoolReintResp + (*PoolQueryResp)(nil), // 64: mgmt.PoolQueryResp + (*PoolQueryTargetResp)(nil), // 65: mgmt.PoolQueryTargetResp + (*PoolSetPropResp)(nil), // 66: mgmt.PoolSetPropResp + (*PoolGetPropResp)(nil), // 67: mgmt.PoolGetPropResp + (*PoolGetCAResp)(nil), // 68: mgmt.PoolGetCAResp + (*PoolAddCAResp)(nil), // 69: mgmt.PoolAddCAResp + (*PoolRemoveCAResp)(nil), // 70: mgmt.PoolRemoveCAResp + (*PoolGetCertWatermarksResp)(nil), // 71: mgmt.PoolGetCertWatermarksResp + (*PoolRevokeClientResp)(nil), // 72: mgmt.PoolRevokeClientResp + (*ACLResp)(nil), // 73: mgmt.ACLResp + (*DaosResp)(nil), // 74: mgmt.DaosResp + (*GetAttachInfoResp)(nil), // 75: mgmt.GetAttachInfoResp + (*ListPoolsResp)(nil), // 76: mgmt.ListPoolsResp + (*ListContResp)(nil), // 77: mgmt.ListContResp + (*SystemQueryResp)(nil), // 78: mgmt.SystemQueryResp + (*SystemStopResp)(nil), // 79: mgmt.SystemStopResp + (*SystemStartResp)(nil), // 80: mgmt.SystemStartResp + (*SystemExcludeResp)(nil), // 81: mgmt.SystemExcludeResp + (*SystemDrainResp)(nil), // 82: mgmt.SystemDrainResp + (*SystemRebuildManageResp)(nil), // 83: mgmt.SystemRebuildManageResp + (*SystemEraseResp)(nil), // 84: mgmt.SystemEraseResp + (*SystemCleanupResp)(nil), // 85: mgmt.SystemCleanupResp + (*CheckStartResp)(nil), // 86: mgmt.CheckStartResp + (*CheckStopResp)(nil), // 87: mgmt.CheckStopResp + (*CheckQueryResp)(nil), // 88: mgmt.CheckQueryResp + (*CheckGetPolicyResp)(nil), // 89: mgmt.CheckGetPolicyResp + (*CheckActResp)(nil), // 90: mgmt.CheckActResp + (*shared.CheckReportResp)(nil), // 91: shared.CheckReportResp + (*SystemGetAttrResp)(nil), // 92: mgmt.SystemGetAttrResp + (*SystemGetPropResp)(nil), // 93: mgmt.SystemGetPropResp } var file_mgmt_mgmt_proto_depIdxs = []int32{ 0, // 0: mgmt.MgmtSvc.Join:input_type -> mgmt.JoinReq @@ -350,96 +382,106 @@ var file_mgmt_mgmt_proto_depIdxs = []int32{ 11, // 11: mgmt.MgmtSvc.PoolQueryTarget:input_type -> mgmt.PoolQueryTargetReq 12, // 12: mgmt.MgmtSvc.PoolSetProp:input_type -> mgmt.PoolSetPropReq 13, // 13: mgmt.MgmtSvc.PoolGetProp:input_type -> mgmt.PoolGetPropReq - 14, // 14: mgmt.MgmtSvc.PoolGetACL:input_type -> mgmt.GetACLReq - 15, // 15: mgmt.MgmtSvc.PoolOverwriteACL:input_type -> mgmt.ModifyACLReq - 15, // 16: mgmt.MgmtSvc.PoolUpdateACL:input_type -> mgmt.ModifyACLReq - 16, // 17: mgmt.MgmtSvc.PoolDeleteACL:input_type -> mgmt.DeleteACLReq - 17, // 18: mgmt.MgmtSvc.PoolUpgrade:input_type -> mgmt.PoolUpgradeReq - 18, // 19: mgmt.MgmtSvc.PoolRebuildStart:input_type -> mgmt.PoolRebuildStartReq - 19, // 20: mgmt.MgmtSvc.PoolRebuildStop:input_type -> mgmt.PoolRebuildStopReq - 20, // 21: mgmt.MgmtSvc.PoolSelfHealEval:input_type -> mgmt.PoolSelfHealEvalReq - 21, // 22: mgmt.MgmtSvc.GetAttachInfo:input_type -> mgmt.GetAttachInfoReq - 22, // 23: mgmt.MgmtSvc.ListPools:input_type -> mgmt.ListPoolsReq - 23, // 24: mgmt.MgmtSvc.ListContainers:input_type -> mgmt.ListContReq - 24, // 25: mgmt.MgmtSvc.ContSetOwner:input_type -> mgmt.ContSetOwnerReq - 25, // 26: mgmt.MgmtSvc.SystemQuery:input_type -> mgmt.SystemQueryReq - 26, // 27: mgmt.MgmtSvc.SystemStop:input_type -> mgmt.SystemStopReq - 27, // 28: mgmt.MgmtSvc.SystemStart:input_type -> mgmt.SystemStartReq - 28, // 29: mgmt.MgmtSvc.SystemExclude:input_type -> mgmt.SystemExcludeReq - 29, // 30: mgmt.MgmtSvc.SystemDrain:input_type -> mgmt.SystemDrainReq - 30, // 31: mgmt.MgmtSvc.SystemRebuildManage:input_type -> mgmt.SystemRebuildManageReq - 31, // 32: mgmt.MgmtSvc.SystemSelfHealEval:input_type -> mgmt.SystemSelfHealEvalReq - 32, // 33: mgmt.MgmtSvc.SystemErase:input_type -> mgmt.SystemEraseReq - 33, // 34: mgmt.MgmtSvc.SystemCleanup:input_type -> mgmt.SystemCleanupReq - 34, // 35: mgmt.MgmtSvc.SystemCheckEnable:input_type -> mgmt.CheckEnableReq - 35, // 36: mgmt.MgmtSvc.SystemCheckDisable:input_type -> mgmt.CheckDisableReq - 36, // 37: mgmt.MgmtSvc.SystemCheckStart:input_type -> mgmt.CheckStartReq - 37, // 38: mgmt.MgmtSvc.SystemCheckStop:input_type -> mgmt.CheckStopReq - 38, // 39: mgmt.MgmtSvc.SystemCheckQuery:input_type -> mgmt.CheckQueryReq - 39, // 40: mgmt.MgmtSvc.SystemCheckSetPolicy:input_type -> mgmt.CheckSetPolicyReq - 40, // 41: mgmt.MgmtSvc.SystemCheckGetPolicy:input_type -> mgmt.CheckGetPolicyReq - 41, // 42: mgmt.MgmtSvc.SystemCheckRepair:input_type -> mgmt.CheckActReq - 42, // 43: mgmt.MgmtSvc.SystemCheckEngineReport:input_type -> shared.CheckReportReq - 43, // 44: mgmt.MgmtSvc.SystemSetAttr:input_type -> mgmt.SystemSetAttrReq - 44, // 45: mgmt.MgmtSvc.SystemGetAttr:input_type -> mgmt.SystemGetAttrReq - 45, // 46: mgmt.MgmtSvc.SystemSetProp:input_type -> mgmt.SystemSetPropReq - 46, // 47: mgmt.MgmtSvc.SystemGetProp:input_type -> mgmt.SystemGetPropReq - 47, // 48: mgmt.MgmtSvc.FaultInjectReport:input_type -> chk.CheckReport - 48, // 49: mgmt.MgmtSvc.FaultInjectPoolFault:input_type -> chk.Fault - 48, // 50: mgmt.MgmtSvc.FaultInjectMgmtPoolFault:input_type -> chk.Fault - 49, // 51: mgmt.MgmtSvc.Join:output_type -> mgmt.JoinResp - 50, // 52: mgmt.MgmtSvc.ClusterEvent:output_type -> shared.ClusterEventResp - 51, // 53: mgmt.MgmtSvc.LeaderQuery:output_type -> mgmt.LeaderQueryResp - 52, // 54: mgmt.MgmtSvc.PoolCreate:output_type -> mgmt.PoolCreateResp - 53, // 55: mgmt.MgmtSvc.PoolDestroy:output_type -> mgmt.PoolDestroyResp - 54, // 56: mgmt.MgmtSvc.PoolEvict:output_type -> mgmt.PoolEvictResp - 55, // 57: mgmt.MgmtSvc.PoolExclude:output_type -> mgmt.PoolExcludeResp - 56, // 58: mgmt.MgmtSvc.PoolDrain:output_type -> mgmt.PoolDrainResp - 57, // 59: mgmt.MgmtSvc.PoolExtend:output_type -> mgmt.PoolExtendResp - 58, // 60: mgmt.MgmtSvc.PoolReintegrate:output_type -> mgmt.PoolReintResp - 59, // 61: mgmt.MgmtSvc.PoolQuery:output_type -> mgmt.PoolQueryResp - 60, // 62: mgmt.MgmtSvc.PoolQueryTarget:output_type -> mgmt.PoolQueryTargetResp - 61, // 63: mgmt.MgmtSvc.PoolSetProp:output_type -> mgmt.PoolSetPropResp - 62, // 64: mgmt.MgmtSvc.PoolGetProp:output_type -> mgmt.PoolGetPropResp - 63, // 65: mgmt.MgmtSvc.PoolGetACL:output_type -> mgmt.ACLResp - 63, // 66: mgmt.MgmtSvc.PoolOverwriteACL:output_type -> mgmt.ACLResp - 63, // 67: mgmt.MgmtSvc.PoolUpdateACL:output_type -> mgmt.ACLResp - 63, // 68: mgmt.MgmtSvc.PoolDeleteACL:output_type -> mgmt.ACLResp - 64, // 69: mgmt.MgmtSvc.PoolUpgrade:output_type -> mgmt.DaosResp - 64, // 70: mgmt.MgmtSvc.PoolRebuildStart:output_type -> mgmt.DaosResp - 64, // 71: mgmt.MgmtSvc.PoolRebuildStop:output_type -> mgmt.DaosResp - 64, // 72: mgmt.MgmtSvc.PoolSelfHealEval:output_type -> mgmt.DaosResp - 65, // 73: mgmt.MgmtSvc.GetAttachInfo:output_type -> mgmt.GetAttachInfoResp - 66, // 74: mgmt.MgmtSvc.ListPools:output_type -> mgmt.ListPoolsResp - 67, // 75: mgmt.MgmtSvc.ListContainers:output_type -> mgmt.ListContResp - 64, // 76: mgmt.MgmtSvc.ContSetOwner:output_type -> mgmt.DaosResp - 68, // 77: mgmt.MgmtSvc.SystemQuery:output_type -> mgmt.SystemQueryResp - 69, // 78: mgmt.MgmtSvc.SystemStop:output_type -> mgmt.SystemStopResp - 70, // 79: mgmt.MgmtSvc.SystemStart:output_type -> mgmt.SystemStartResp - 71, // 80: mgmt.MgmtSvc.SystemExclude:output_type -> mgmt.SystemExcludeResp - 72, // 81: mgmt.MgmtSvc.SystemDrain:output_type -> mgmt.SystemDrainResp - 73, // 82: mgmt.MgmtSvc.SystemRebuildManage:output_type -> mgmt.SystemRebuildManageResp - 64, // 83: mgmt.MgmtSvc.SystemSelfHealEval:output_type -> mgmt.DaosResp - 74, // 84: mgmt.MgmtSvc.SystemErase:output_type -> mgmt.SystemEraseResp - 75, // 85: mgmt.MgmtSvc.SystemCleanup:output_type -> mgmt.SystemCleanupResp - 64, // 86: mgmt.MgmtSvc.SystemCheckEnable:output_type -> mgmt.DaosResp - 64, // 87: mgmt.MgmtSvc.SystemCheckDisable:output_type -> mgmt.DaosResp - 76, // 88: mgmt.MgmtSvc.SystemCheckStart:output_type -> mgmt.CheckStartResp - 77, // 89: mgmt.MgmtSvc.SystemCheckStop:output_type -> mgmt.CheckStopResp - 78, // 90: mgmt.MgmtSvc.SystemCheckQuery:output_type -> mgmt.CheckQueryResp - 64, // 91: mgmt.MgmtSvc.SystemCheckSetPolicy:output_type -> mgmt.DaosResp - 79, // 92: mgmt.MgmtSvc.SystemCheckGetPolicy:output_type -> mgmt.CheckGetPolicyResp - 80, // 93: mgmt.MgmtSvc.SystemCheckRepair:output_type -> mgmt.CheckActResp - 81, // 94: mgmt.MgmtSvc.SystemCheckEngineReport:output_type -> shared.CheckReportResp - 64, // 95: mgmt.MgmtSvc.SystemSetAttr:output_type -> mgmt.DaosResp - 82, // 96: mgmt.MgmtSvc.SystemGetAttr:output_type -> mgmt.SystemGetAttrResp - 64, // 97: mgmt.MgmtSvc.SystemSetProp:output_type -> mgmt.DaosResp - 83, // 98: mgmt.MgmtSvc.SystemGetProp:output_type -> mgmt.SystemGetPropResp - 64, // 99: mgmt.MgmtSvc.FaultInjectReport:output_type -> mgmt.DaosResp - 64, // 100: mgmt.MgmtSvc.FaultInjectPoolFault:output_type -> mgmt.DaosResp - 64, // 101: mgmt.MgmtSvc.FaultInjectMgmtPoolFault:output_type -> mgmt.DaosResp - 51, // [51:102] is the sub-list for method output_type - 0, // [0:51] is the sub-list for method input_type + 14, // 14: mgmt.MgmtSvc.PoolGetCA:input_type -> mgmt.PoolGetCAReq + 15, // 15: mgmt.MgmtSvc.PoolAddCA:input_type -> mgmt.PoolAddCAReq + 16, // 16: mgmt.MgmtSvc.PoolRemoveCA:input_type -> mgmt.PoolRemoveCAReq + 17, // 17: mgmt.MgmtSvc.PoolGetCertWatermarks:input_type -> mgmt.PoolGetCertWatermarksReq + 18, // 18: mgmt.MgmtSvc.PoolRevokeClient:input_type -> mgmt.PoolRevokeClientReq + 19, // 19: mgmt.MgmtSvc.PoolGetACL:input_type -> mgmt.GetACLReq + 20, // 20: mgmt.MgmtSvc.PoolOverwriteACL:input_type -> mgmt.ModifyACLReq + 20, // 21: mgmt.MgmtSvc.PoolUpdateACL:input_type -> mgmt.ModifyACLReq + 21, // 22: mgmt.MgmtSvc.PoolDeleteACL:input_type -> mgmt.DeleteACLReq + 22, // 23: mgmt.MgmtSvc.PoolUpgrade:input_type -> mgmt.PoolUpgradeReq + 23, // 24: mgmt.MgmtSvc.PoolRebuildStart:input_type -> mgmt.PoolRebuildStartReq + 24, // 25: mgmt.MgmtSvc.PoolRebuildStop:input_type -> mgmt.PoolRebuildStopReq + 25, // 26: mgmt.MgmtSvc.PoolSelfHealEval:input_type -> mgmt.PoolSelfHealEvalReq + 26, // 27: mgmt.MgmtSvc.GetAttachInfo:input_type -> mgmt.GetAttachInfoReq + 27, // 28: mgmt.MgmtSvc.ListPools:input_type -> mgmt.ListPoolsReq + 28, // 29: mgmt.MgmtSvc.ListContainers:input_type -> mgmt.ListContReq + 29, // 30: mgmt.MgmtSvc.ContSetOwner:input_type -> mgmt.ContSetOwnerReq + 30, // 31: mgmt.MgmtSvc.SystemQuery:input_type -> mgmt.SystemQueryReq + 31, // 32: mgmt.MgmtSvc.SystemStop:input_type -> mgmt.SystemStopReq + 32, // 33: mgmt.MgmtSvc.SystemStart:input_type -> mgmt.SystemStartReq + 33, // 34: mgmt.MgmtSvc.SystemExclude:input_type -> mgmt.SystemExcludeReq + 34, // 35: mgmt.MgmtSvc.SystemDrain:input_type -> mgmt.SystemDrainReq + 35, // 36: mgmt.MgmtSvc.SystemRebuildManage:input_type -> mgmt.SystemRebuildManageReq + 36, // 37: mgmt.MgmtSvc.SystemSelfHealEval:input_type -> mgmt.SystemSelfHealEvalReq + 37, // 38: mgmt.MgmtSvc.SystemErase:input_type -> mgmt.SystemEraseReq + 38, // 39: mgmt.MgmtSvc.SystemCleanup:input_type -> mgmt.SystemCleanupReq + 39, // 40: mgmt.MgmtSvc.SystemCheckEnable:input_type -> mgmt.CheckEnableReq + 40, // 41: mgmt.MgmtSvc.SystemCheckDisable:input_type -> mgmt.CheckDisableReq + 41, // 42: mgmt.MgmtSvc.SystemCheckStart:input_type -> mgmt.CheckStartReq + 42, // 43: mgmt.MgmtSvc.SystemCheckStop:input_type -> mgmt.CheckStopReq + 43, // 44: mgmt.MgmtSvc.SystemCheckQuery:input_type -> mgmt.CheckQueryReq + 44, // 45: mgmt.MgmtSvc.SystemCheckSetPolicy:input_type -> mgmt.CheckSetPolicyReq + 45, // 46: mgmt.MgmtSvc.SystemCheckGetPolicy:input_type -> mgmt.CheckGetPolicyReq + 46, // 47: mgmt.MgmtSvc.SystemCheckRepair:input_type -> mgmt.CheckActReq + 47, // 48: mgmt.MgmtSvc.SystemCheckEngineReport:input_type -> shared.CheckReportReq + 48, // 49: mgmt.MgmtSvc.SystemSetAttr:input_type -> mgmt.SystemSetAttrReq + 49, // 50: mgmt.MgmtSvc.SystemGetAttr:input_type -> mgmt.SystemGetAttrReq + 50, // 51: mgmt.MgmtSvc.SystemSetProp:input_type -> mgmt.SystemSetPropReq + 51, // 52: mgmt.MgmtSvc.SystemGetProp:input_type -> mgmt.SystemGetPropReq + 52, // 53: mgmt.MgmtSvc.FaultInjectReport:input_type -> chk.CheckReport + 53, // 54: mgmt.MgmtSvc.FaultInjectPoolFault:input_type -> chk.Fault + 53, // 55: mgmt.MgmtSvc.FaultInjectMgmtPoolFault:input_type -> chk.Fault + 54, // 56: mgmt.MgmtSvc.Join:output_type -> mgmt.JoinResp + 55, // 57: mgmt.MgmtSvc.ClusterEvent:output_type -> shared.ClusterEventResp + 56, // 58: mgmt.MgmtSvc.LeaderQuery:output_type -> mgmt.LeaderQueryResp + 57, // 59: mgmt.MgmtSvc.PoolCreate:output_type -> mgmt.PoolCreateResp + 58, // 60: mgmt.MgmtSvc.PoolDestroy:output_type -> mgmt.PoolDestroyResp + 59, // 61: mgmt.MgmtSvc.PoolEvict:output_type -> mgmt.PoolEvictResp + 60, // 62: mgmt.MgmtSvc.PoolExclude:output_type -> mgmt.PoolExcludeResp + 61, // 63: mgmt.MgmtSvc.PoolDrain:output_type -> mgmt.PoolDrainResp + 62, // 64: mgmt.MgmtSvc.PoolExtend:output_type -> mgmt.PoolExtendResp + 63, // 65: mgmt.MgmtSvc.PoolReintegrate:output_type -> mgmt.PoolReintResp + 64, // 66: mgmt.MgmtSvc.PoolQuery:output_type -> mgmt.PoolQueryResp + 65, // 67: mgmt.MgmtSvc.PoolQueryTarget:output_type -> mgmt.PoolQueryTargetResp + 66, // 68: mgmt.MgmtSvc.PoolSetProp:output_type -> mgmt.PoolSetPropResp + 67, // 69: mgmt.MgmtSvc.PoolGetProp:output_type -> mgmt.PoolGetPropResp + 68, // 70: mgmt.MgmtSvc.PoolGetCA:output_type -> mgmt.PoolGetCAResp + 69, // 71: mgmt.MgmtSvc.PoolAddCA:output_type -> mgmt.PoolAddCAResp + 70, // 72: mgmt.MgmtSvc.PoolRemoveCA:output_type -> mgmt.PoolRemoveCAResp + 71, // 73: mgmt.MgmtSvc.PoolGetCertWatermarks:output_type -> mgmt.PoolGetCertWatermarksResp + 72, // 74: mgmt.MgmtSvc.PoolRevokeClient:output_type -> mgmt.PoolRevokeClientResp + 73, // 75: mgmt.MgmtSvc.PoolGetACL:output_type -> mgmt.ACLResp + 73, // 76: mgmt.MgmtSvc.PoolOverwriteACL:output_type -> mgmt.ACLResp + 73, // 77: mgmt.MgmtSvc.PoolUpdateACL:output_type -> mgmt.ACLResp + 73, // 78: mgmt.MgmtSvc.PoolDeleteACL:output_type -> mgmt.ACLResp + 74, // 79: mgmt.MgmtSvc.PoolUpgrade:output_type -> mgmt.DaosResp + 74, // 80: mgmt.MgmtSvc.PoolRebuildStart:output_type -> mgmt.DaosResp + 74, // 81: mgmt.MgmtSvc.PoolRebuildStop:output_type -> mgmt.DaosResp + 74, // 82: mgmt.MgmtSvc.PoolSelfHealEval:output_type -> mgmt.DaosResp + 75, // 83: mgmt.MgmtSvc.GetAttachInfo:output_type -> mgmt.GetAttachInfoResp + 76, // 84: mgmt.MgmtSvc.ListPools:output_type -> mgmt.ListPoolsResp + 77, // 85: mgmt.MgmtSvc.ListContainers:output_type -> mgmt.ListContResp + 74, // 86: mgmt.MgmtSvc.ContSetOwner:output_type -> mgmt.DaosResp + 78, // 87: mgmt.MgmtSvc.SystemQuery:output_type -> mgmt.SystemQueryResp + 79, // 88: mgmt.MgmtSvc.SystemStop:output_type -> mgmt.SystemStopResp + 80, // 89: mgmt.MgmtSvc.SystemStart:output_type -> mgmt.SystemStartResp + 81, // 90: mgmt.MgmtSvc.SystemExclude:output_type -> mgmt.SystemExcludeResp + 82, // 91: mgmt.MgmtSvc.SystemDrain:output_type -> mgmt.SystemDrainResp + 83, // 92: mgmt.MgmtSvc.SystemRebuildManage:output_type -> mgmt.SystemRebuildManageResp + 74, // 93: mgmt.MgmtSvc.SystemSelfHealEval:output_type -> mgmt.DaosResp + 84, // 94: mgmt.MgmtSvc.SystemErase:output_type -> mgmt.SystemEraseResp + 85, // 95: mgmt.MgmtSvc.SystemCleanup:output_type -> mgmt.SystemCleanupResp + 74, // 96: mgmt.MgmtSvc.SystemCheckEnable:output_type -> mgmt.DaosResp + 74, // 97: mgmt.MgmtSvc.SystemCheckDisable:output_type -> mgmt.DaosResp + 86, // 98: mgmt.MgmtSvc.SystemCheckStart:output_type -> mgmt.CheckStartResp + 87, // 99: mgmt.MgmtSvc.SystemCheckStop:output_type -> mgmt.CheckStopResp + 88, // 100: mgmt.MgmtSvc.SystemCheckQuery:output_type -> mgmt.CheckQueryResp + 74, // 101: mgmt.MgmtSvc.SystemCheckSetPolicy:output_type -> mgmt.DaosResp + 89, // 102: mgmt.MgmtSvc.SystemCheckGetPolicy:output_type -> mgmt.CheckGetPolicyResp + 90, // 103: mgmt.MgmtSvc.SystemCheckRepair:output_type -> mgmt.CheckActResp + 91, // 104: mgmt.MgmtSvc.SystemCheckEngineReport:output_type -> shared.CheckReportResp + 74, // 105: mgmt.MgmtSvc.SystemSetAttr:output_type -> mgmt.DaosResp + 92, // 106: mgmt.MgmtSvc.SystemGetAttr:output_type -> mgmt.SystemGetAttrResp + 74, // 107: mgmt.MgmtSvc.SystemSetProp:output_type -> mgmt.DaosResp + 93, // 108: mgmt.MgmtSvc.SystemGetProp:output_type -> mgmt.SystemGetPropResp + 74, // 109: mgmt.MgmtSvc.FaultInjectReport:output_type -> mgmt.DaosResp + 74, // 110: mgmt.MgmtSvc.FaultInjectPoolFault:output_type -> mgmt.DaosResp + 74, // 111: mgmt.MgmtSvc.FaultInjectMgmtPoolFault:output_type -> mgmt.DaosResp + 56, // [56:112] is the sub-list for method output_type + 0, // [0:56] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/src/control/common/proto/mgmt/mgmt_grpc.pb.go b/src/control/common/proto/mgmt/mgmt_grpc.pb.go index 66fd24bef0a..4851a71f470 100644 --- a/src/control/common/proto/mgmt/mgmt_grpc.pb.go +++ b/src/control/common/proto/mgmt/mgmt_grpc.pb.go @@ -7,7 +7,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.1 // - protoc v3.14.0 // source: mgmt/mgmt.proto @@ -42,6 +42,11 @@ const ( MgmtSvc_PoolQueryTarget_FullMethodName = "/mgmt.MgmtSvc/PoolQueryTarget" MgmtSvc_PoolSetProp_FullMethodName = "/mgmt.MgmtSvc/PoolSetProp" MgmtSvc_PoolGetProp_FullMethodName = "/mgmt.MgmtSvc/PoolGetProp" + MgmtSvc_PoolGetCA_FullMethodName = "/mgmt.MgmtSvc/PoolGetCA" + MgmtSvc_PoolAddCA_FullMethodName = "/mgmt.MgmtSvc/PoolAddCA" + MgmtSvc_PoolRemoveCA_FullMethodName = "/mgmt.MgmtSvc/PoolRemoveCA" + MgmtSvc_PoolGetCertWatermarks_FullMethodName = "/mgmt.MgmtSvc/PoolGetCertWatermarks" + MgmtSvc_PoolRevokeClient_FullMethodName = "/mgmt.MgmtSvc/PoolRevokeClient" MgmtSvc_PoolGetACL_FullMethodName = "/mgmt.MgmtSvc/PoolGetACL" MgmtSvc_PoolOverwriteACL_FullMethodName = "/mgmt.MgmtSvc/PoolOverwriteACL" MgmtSvc_PoolUpdateACL_FullMethodName = "/mgmt.MgmtSvc/PoolUpdateACL" @@ -121,6 +126,16 @@ type MgmtSvcClient interface { PoolSetProp(ctx context.Context, in *PoolSetPropReq, opts ...grpc.CallOption) (*PoolSetPropResp, error) // Get a DAOS pool property list. PoolGetProp(ctx context.Context, in *PoolGetPropReq, opts ...grpc.CallOption) (*PoolGetPropResp, error) + // Read the pool's CA bundle. + PoolGetCA(ctx context.Context, in *PoolGetCAReq, opts ...grpc.CallOption) (*PoolGetCAResp, error) + // Append a CA certificate to the pool's CA bundle. + PoolAddCA(ctx context.Context, in *PoolAddCAReq, opts ...grpc.CallOption) (*PoolAddCAResp, error) + // Remove one or all CA certificates from the pool's CA bundle. + PoolRemoveCA(ctx context.Context, in *PoolRemoveCAReq, opts ...grpc.CallOption) (*PoolRemoveCAResp, error) + // Read the per-CN revocation watermarks for the pool. + PoolGetCertWatermarks(ctx context.Context, in *PoolGetCertWatermarksReq, opts ...grpc.CallOption) (*PoolGetCertWatermarksResp, error) + // Advance the cert revocation watermark for a given CN. + PoolRevokeClient(ctx context.Context, in *PoolRevokeClientReq, opts ...grpc.CallOption) (*PoolRevokeClientResp, error) // Fetch the Access Control List for a DAOS pool. PoolGetACL(ctx context.Context, in *GetACLReq, opts ...grpc.CallOption) (*ACLResp, error) // Overwrite the Access Control List for a DAOS pool with a new one. @@ -345,6 +360,56 @@ func (c *mgmtSvcClient) PoolGetProp(ctx context.Context, in *PoolGetPropReq, opt return out, nil } +func (c *mgmtSvcClient) PoolGetCA(ctx context.Context, in *PoolGetCAReq, opts ...grpc.CallOption) (*PoolGetCAResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PoolGetCAResp) + err := c.cc.Invoke(ctx, MgmtSvc_PoolGetCA_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *mgmtSvcClient) PoolAddCA(ctx context.Context, in *PoolAddCAReq, opts ...grpc.CallOption) (*PoolAddCAResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PoolAddCAResp) + err := c.cc.Invoke(ctx, MgmtSvc_PoolAddCA_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *mgmtSvcClient) PoolRemoveCA(ctx context.Context, in *PoolRemoveCAReq, opts ...grpc.CallOption) (*PoolRemoveCAResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PoolRemoveCAResp) + err := c.cc.Invoke(ctx, MgmtSvc_PoolRemoveCA_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *mgmtSvcClient) PoolGetCertWatermarks(ctx context.Context, in *PoolGetCertWatermarksReq, opts ...grpc.CallOption) (*PoolGetCertWatermarksResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PoolGetCertWatermarksResp) + err := c.cc.Invoke(ctx, MgmtSvc_PoolGetCertWatermarks_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *mgmtSvcClient) PoolRevokeClient(ctx context.Context, in *PoolRevokeClientReq, opts ...grpc.CallOption) (*PoolRevokeClientResp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PoolRevokeClientResp) + err := c.cc.Invoke(ctx, MgmtSvc_PoolRevokeClient_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *mgmtSvcClient) PoolGetACL(ctx context.Context, in *GetACLReq, opts ...grpc.CallOption) (*ACLResp, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ACLResp) @@ -755,6 +820,16 @@ type MgmtSvcServer interface { PoolSetProp(context.Context, *PoolSetPropReq) (*PoolSetPropResp, error) // Get a DAOS pool property list. PoolGetProp(context.Context, *PoolGetPropReq) (*PoolGetPropResp, error) + // Read the pool's CA bundle. + PoolGetCA(context.Context, *PoolGetCAReq) (*PoolGetCAResp, error) + // Append a CA certificate to the pool's CA bundle. + PoolAddCA(context.Context, *PoolAddCAReq) (*PoolAddCAResp, error) + // Remove one or all CA certificates from the pool's CA bundle. + PoolRemoveCA(context.Context, *PoolRemoveCAReq) (*PoolRemoveCAResp, error) + // Read the per-CN revocation watermarks for the pool. + PoolGetCertWatermarks(context.Context, *PoolGetCertWatermarksReq) (*PoolGetCertWatermarksResp, error) + // Advance the cert revocation watermark for a given CN. + PoolRevokeClient(context.Context, *PoolRevokeClientReq) (*PoolRevokeClientResp, error) // Fetch the Access Control List for a DAOS pool. PoolGetACL(context.Context, *GetACLReq) (*ACLResp, error) // Overwrite the Access Control List for a DAOS pool with a new one. @@ -840,157 +915,172 @@ type MgmtSvcServer interface { type UnimplementedMgmtSvcServer struct{} func (UnimplementedMgmtSvcServer) Join(context.Context, *JoinReq) (*JoinResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method Join not implemented") + return nil, status.Error(codes.Unimplemented, "method Join not implemented") } func (UnimplementedMgmtSvcServer) ClusterEvent(context.Context, *shared.ClusterEventReq) (*shared.ClusterEventResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClusterEvent not implemented") + return nil, status.Error(codes.Unimplemented, "method ClusterEvent not implemented") } func (UnimplementedMgmtSvcServer) LeaderQuery(context.Context, *LeaderQueryReq) (*LeaderQueryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method LeaderQuery not implemented") + return nil, status.Error(codes.Unimplemented, "method LeaderQuery not implemented") } func (UnimplementedMgmtSvcServer) PoolCreate(context.Context, *PoolCreateReq) (*PoolCreateResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolCreate not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolCreate not implemented") } func (UnimplementedMgmtSvcServer) PoolDestroy(context.Context, *PoolDestroyReq) (*PoolDestroyResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolDestroy not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolDestroy not implemented") } func (UnimplementedMgmtSvcServer) PoolEvict(context.Context, *PoolEvictReq) (*PoolEvictResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolEvict not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolEvict not implemented") } func (UnimplementedMgmtSvcServer) PoolExclude(context.Context, *PoolExcludeReq) (*PoolExcludeResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolExclude not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolExclude not implemented") } func (UnimplementedMgmtSvcServer) PoolDrain(context.Context, *PoolDrainReq) (*PoolDrainResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolDrain not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolDrain not implemented") } func (UnimplementedMgmtSvcServer) PoolExtend(context.Context, *PoolExtendReq) (*PoolExtendResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolExtend not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolExtend not implemented") } func (UnimplementedMgmtSvcServer) PoolReintegrate(context.Context, *PoolReintReq) (*PoolReintResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolReintegrate not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolReintegrate not implemented") } func (UnimplementedMgmtSvcServer) PoolQuery(context.Context, *PoolQueryReq) (*PoolQueryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolQuery not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolQuery not implemented") } func (UnimplementedMgmtSvcServer) PoolQueryTarget(context.Context, *PoolQueryTargetReq) (*PoolQueryTargetResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolQueryTarget not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolQueryTarget not implemented") } func (UnimplementedMgmtSvcServer) PoolSetProp(context.Context, *PoolSetPropReq) (*PoolSetPropResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolSetProp not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolSetProp not implemented") } func (UnimplementedMgmtSvcServer) PoolGetProp(context.Context, *PoolGetPropReq) (*PoolGetPropResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolGetProp not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolGetProp not implemented") +} +func (UnimplementedMgmtSvcServer) PoolGetCA(context.Context, *PoolGetCAReq) (*PoolGetCAResp, error) { + return nil, status.Error(codes.Unimplemented, "method PoolGetCA not implemented") +} +func (UnimplementedMgmtSvcServer) PoolAddCA(context.Context, *PoolAddCAReq) (*PoolAddCAResp, error) { + return nil, status.Error(codes.Unimplemented, "method PoolAddCA not implemented") +} +func (UnimplementedMgmtSvcServer) PoolRemoveCA(context.Context, *PoolRemoveCAReq) (*PoolRemoveCAResp, error) { + return nil, status.Error(codes.Unimplemented, "method PoolRemoveCA not implemented") +} +func (UnimplementedMgmtSvcServer) PoolGetCertWatermarks(context.Context, *PoolGetCertWatermarksReq) (*PoolGetCertWatermarksResp, error) { + return nil, status.Error(codes.Unimplemented, "method PoolGetCertWatermarks not implemented") +} +func (UnimplementedMgmtSvcServer) PoolRevokeClient(context.Context, *PoolRevokeClientReq) (*PoolRevokeClientResp, error) { + return nil, status.Error(codes.Unimplemented, "method PoolRevokeClient not implemented") } func (UnimplementedMgmtSvcServer) PoolGetACL(context.Context, *GetACLReq) (*ACLResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolGetACL not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolGetACL not implemented") } func (UnimplementedMgmtSvcServer) PoolOverwriteACL(context.Context, *ModifyACLReq) (*ACLResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolOverwriteACL not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolOverwriteACL not implemented") } func (UnimplementedMgmtSvcServer) PoolUpdateACL(context.Context, *ModifyACLReq) (*ACLResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolUpdateACL not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolUpdateACL not implemented") } func (UnimplementedMgmtSvcServer) PoolDeleteACL(context.Context, *DeleteACLReq) (*ACLResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolDeleteACL not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolDeleteACL not implemented") } func (UnimplementedMgmtSvcServer) PoolUpgrade(context.Context, *PoolUpgradeReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolUpgrade not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolUpgrade not implemented") } func (UnimplementedMgmtSvcServer) PoolRebuildStart(context.Context, *PoolRebuildStartReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolRebuildStart not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolRebuildStart not implemented") } func (UnimplementedMgmtSvcServer) PoolRebuildStop(context.Context, *PoolRebuildStopReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolRebuildStop not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolRebuildStop not implemented") } func (UnimplementedMgmtSvcServer) PoolSelfHealEval(context.Context, *PoolSelfHealEvalReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method PoolSelfHealEval not implemented") + return nil, status.Error(codes.Unimplemented, "method PoolSelfHealEval not implemented") } func (UnimplementedMgmtSvcServer) GetAttachInfo(context.Context, *GetAttachInfoReq) (*GetAttachInfoResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetAttachInfo not implemented") + return nil, status.Error(codes.Unimplemented, "method GetAttachInfo not implemented") } func (UnimplementedMgmtSvcServer) ListPools(context.Context, *ListPoolsReq) (*ListPoolsResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListPools not implemented") + return nil, status.Error(codes.Unimplemented, "method ListPools not implemented") } func (UnimplementedMgmtSvcServer) ListContainers(context.Context, *ListContReq) (*ListContResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListContainers not implemented") + return nil, status.Error(codes.Unimplemented, "method ListContainers not implemented") } func (UnimplementedMgmtSvcServer) ContSetOwner(context.Context, *ContSetOwnerReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method ContSetOwner not implemented") + return nil, status.Error(codes.Unimplemented, "method ContSetOwner not implemented") } func (UnimplementedMgmtSvcServer) SystemQuery(context.Context, *SystemQueryReq) (*SystemQueryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemQuery not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemQuery not implemented") } func (UnimplementedMgmtSvcServer) SystemStop(context.Context, *SystemStopReq) (*SystemStopResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemStop not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemStop not implemented") } func (UnimplementedMgmtSvcServer) SystemStart(context.Context, *SystemStartReq) (*SystemStartResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemStart not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemStart not implemented") } func (UnimplementedMgmtSvcServer) SystemExclude(context.Context, *SystemExcludeReq) (*SystemExcludeResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemExclude not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemExclude not implemented") } func (UnimplementedMgmtSvcServer) SystemDrain(context.Context, *SystemDrainReq) (*SystemDrainResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemDrain not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemDrain not implemented") } func (UnimplementedMgmtSvcServer) SystemRebuildManage(context.Context, *SystemRebuildManageReq) (*SystemRebuildManageResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemRebuildManage not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemRebuildManage not implemented") } func (UnimplementedMgmtSvcServer) SystemSelfHealEval(context.Context, *SystemSelfHealEvalReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemSelfHealEval not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemSelfHealEval not implemented") } func (UnimplementedMgmtSvcServer) SystemErase(context.Context, *SystemEraseReq) (*SystemEraseResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemErase not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemErase not implemented") } func (UnimplementedMgmtSvcServer) SystemCleanup(context.Context, *SystemCleanupReq) (*SystemCleanupResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCleanup not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCleanup not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckEnable(context.Context, *CheckEnableReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckEnable not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckEnable not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckDisable(context.Context, *CheckDisableReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckDisable not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckDisable not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckStart(context.Context, *CheckStartReq) (*CheckStartResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckStart not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckStart not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckStop(context.Context, *CheckStopReq) (*CheckStopResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckStop not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckStop not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckQuery(context.Context, *CheckQueryReq) (*CheckQueryResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckQuery not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckQuery not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckSetPolicy(context.Context, *CheckSetPolicyReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckSetPolicy not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckSetPolicy not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckGetPolicy(context.Context, *CheckGetPolicyReq) (*CheckGetPolicyResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckGetPolicy not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckGetPolicy not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckRepair(context.Context, *CheckActReq) (*CheckActResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckRepair not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckRepair not implemented") } func (UnimplementedMgmtSvcServer) SystemCheckEngineReport(context.Context, *shared.CheckReportReq) (*shared.CheckReportResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemCheckEngineReport not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemCheckEngineReport not implemented") } func (UnimplementedMgmtSvcServer) SystemSetAttr(context.Context, *SystemSetAttrReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemSetAttr not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemSetAttr not implemented") } func (UnimplementedMgmtSvcServer) SystemGetAttr(context.Context, *SystemGetAttrReq) (*SystemGetAttrResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemGetAttr not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemGetAttr not implemented") } func (UnimplementedMgmtSvcServer) SystemSetProp(context.Context, *SystemSetPropReq) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemSetProp not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemSetProp not implemented") } func (UnimplementedMgmtSvcServer) SystemGetProp(context.Context, *SystemGetPropReq) (*SystemGetPropResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method SystemGetProp not implemented") + return nil, status.Error(codes.Unimplemented, "method SystemGetProp not implemented") } func (UnimplementedMgmtSvcServer) FaultInjectReport(context.Context, *chk.CheckReport) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method FaultInjectReport not implemented") + return nil, status.Error(codes.Unimplemented, "method FaultInjectReport not implemented") } func (UnimplementedMgmtSvcServer) FaultInjectPoolFault(context.Context, *chk.Fault) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method FaultInjectPoolFault not implemented") + return nil, status.Error(codes.Unimplemented, "method FaultInjectPoolFault not implemented") } func (UnimplementedMgmtSvcServer) FaultInjectMgmtPoolFault(context.Context, *chk.Fault) (*DaosResp, error) { - return nil, status.Errorf(codes.Unimplemented, "method FaultInjectMgmtPoolFault not implemented") + return nil, status.Error(codes.Unimplemented, "method FaultInjectMgmtPoolFault not implemented") } func (UnimplementedMgmtSvcServer) mustEmbedUnimplementedMgmtSvcServer() {} func (UnimplementedMgmtSvcServer) testEmbeddedByValue() {} @@ -1003,7 +1093,7 @@ type UnsafeMgmtSvcServer interface { } func RegisterMgmtSvcServer(s grpc.ServiceRegistrar, srv MgmtSvcServer) { - // If the following call pancis, it indicates UnimplementedMgmtSvcServer was + // If the following call panics, it indicates UnimplementedMgmtSvcServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. @@ -1265,6 +1355,96 @@ func _MgmtSvc_PoolGetProp_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _MgmtSvc_PoolGetCA_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PoolGetCAReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MgmtSvcServer).PoolGetCA(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MgmtSvc_PoolGetCA_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MgmtSvcServer).PoolGetCA(ctx, req.(*PoolGetCAReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _MgmtSvc_PoolAddCA_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PoolAddCAReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MgmtSvcServer).PoolAddCA(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MgmtSvc_PoolAddCA_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MgmtSvcServer).PoolAddCA(ctx, req.(*PoolAddCAReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _MgmtSvc_PoolRemoveCA_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PoolRemoveCAReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MgmtSvcServer).PoolRemoveCA(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MgmtSvc_PoolRemoveCA_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MgmtSvcServer).PoolRemoveCA(ctx, req.(*PoolRemoveCAReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _MgmtSvc_PoolGetCertWatermarks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PoolGetCertWatermarksReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MgmtSvcServer).PoolGetCertWatermarks(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MgmtSvc_PoolGetCertWatermarks_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MgmtSvcServer).PoolGetCertWatermarks(ctx, req.(*PoolGetCertWatermarksReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _MgmtSvc_PoolRevokeClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PoolRevokeClientReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MgmtSvcServer).PoolRevokeClient(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MgmtSvc_PoolRevokeClient_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MgmtSvcServer).PoolRevokeClient(ctx, req.(*PoolRevokeClientReq)) + } + return interceptor(ctx, in, info, handler) +} + func _MgmtSvc_PoolGetACL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetACLReq) if err := dec(in); err != nil { @@ -1994,6 +2174,26 @@ var MgmtSvc_ServiceDesc = grpc.ServiceDesc{ MethodName: "PoolGetProp", Handler: _MgmtSvc_PoolGetProp_Handler, }, + { + MethodName: "PoolGetCA", + Handler: _MgmtSvc_PoolGetCA_Handler, + }, + { + MethodName: "PoolAddCA", + Handler: _MgmtSvc_PoolAddCA_Handler, + }, + { + MethodName: "PoolRemoveCA", + Handler: _MgmtSvc_PoolRemoveCA_Handler, + }, + { + MethodName: "PoolGetCertWatermarks", + Handler: _MgmtSvc_PoolGetCertWatermarks_Handler, + }, + { + MethodName: "PoolRevokeClient", + Handler: _MgmtSvc_PoolRevokeClient_Handler, + }, { MethodName: "PoolGetACL", Handler: _MgmtSvc_PoolGetACL_Handler, diff --git a/src/control/common/proto/mgmt/pool.pb.go b/src/control/common/proto/mgmt/pool.pb.go index d3c3dacaebc..5ef1495eac3 100644 --- a/src/control/common/proto/mgmt/pool.pb.go +++ b/src/control/common/proto/mgmt/pool.pb.go @@ -250,6 +250,55 @@ func (PoolQueryTargetInfo_TargetState) EnumDescriptor() ([]byte, []int) { return file_mgmt_pool_proto_rawDescGZIP(), []int{30, 0} } +type PoolRevokeClientReq_EvictMode int32 + +const ( + PoolRevokeClientReq_EVICT_DEFAULT PoolRevokeClientReq_EvictMode = 0 // per-CN for node:, pool-wide for tenant: + PoolRevokeClientReq_EVICT_POOL_WIDE PoolRevokeClientReq_EvictMode = 1 // always evict all handles on the pool + PoolRevokeClientReq_EVICT_NONE PoolRevokeClientReq_EvictMode = 2 // advance watermark, leave handles alive +) + +// Enum value maps for PoolRevokeClientReq_EvictMode. +var ( + PoolRevokeClientReq_EvictMode_name = map[int32]string{ + 0: "EVICT_DEFAULT", + 1: "EVICT_POOL_WIDE", + 2: "EVICT_NONE", + } + PoolRevokeClientReq_EvictMode_value = map[string]int32{ + "EVICT_DEFAULT": 0, + "EVICT_POOL_WIDE": 1, + "EVICT_NONE": 2, + } +) + +func (x PoolRevokeClientReq_EvictMode) Enum() *PoolRevokeClientReq_EvictMode { + p := new(PoolRevokeClientReq_EvictMode) + *p = x + return p +} + +func (x PoolRevokeClientReq_EvictMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PoolRevokeClientReq_EvictMode) Descriptor() protoreflect.EnumDescriptor { + return file_mgmt_pool_proto_enumTypes[4].Descriptor() +} + +func (PoolRevokeClientReq_EvictMode) Type() protoreflect.EnumType { + return &file_mgmt_pool_proto_enumTypes[4] +} + +func (x PoolRevokeClientReq_EvictMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PoolRevokeClientReq_EvictMode.Descriptor instead. +func (PoolRevokeClientReq_EvictMode) EnumDescriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{43, 0} +} + // PoolCreateReq supplies new pool parameters. type PoolCreateReq struct { state protoimpl.MessageState @@ -2957,20 +3006,19 @@ func (x *PoolSelfHealEvalReq) GetSvcRanks() []uint32 { return nil } -type ListPoolsResp_Pool struct { +// PoolGetCAReq fetches the pool's CA bundle. +type PoolGetCAReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // uuid of pool - Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` // pool label - SvcReps []uint32 `protobuf:"varint,3,rep,packed,name=svc_reps,json=svcReps,proto3" json:"svc_reps,omitempty"` // pool service replica ranks - State string `protobuf:"bytes,4,opt,name=state,proto3" json:"state,omitempty"` // pool state - RebuildState string `protobuf:"bytes,5,opt,name=rebuild_state,json=rebuildState,proto3" json:"rebuild_state,omitempty"` // pool rebuild state + Sys string `protobuf:"bytes,1,opt,name=sys,proto3" json:"sys,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + SvcRanks []uint32 `protobuf:"varint,3,rep,packed,name=svc_ranks,json=svcRanks,proto3" json:"svc_ranks,omitempty"` } -func (x *ListPoolsResp_Pool) Reset() { - *x = ListPoolsResp_Pool{} +func (x *PoolGetCAReq) Reset() { + *x = PoolGetCAReq{} if protoimpl.UnsafeEnabled { mi := &file_mgmt_pool_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2978,13 +3026,13 @@ func (x *ListPoolsResp_Pool) Reset() { } } -func (x *ListPoolsResp_Pool) String() string { +func (x *PoolGetCAReq) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ListPoolsResp_Pool) ProtoMessage() {} +func (*PoolGetCAReq) ProtoMessage() {} -func (x *ListPoolsResp_Pool) ProtoReflect() protoreflect.Message { +func (x *PoolGetCAReq) ProtoReflect() protoreflect.Message { mi := &file_mgmt_pool_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2996,71 +3044,201 @@ func (x *ListPoolsResp_Pool) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ListPoolsResp_Pool.ProtoReflect.Descriptor instead. -func (*ListPoolsResp_Pool) Descriptor() ([]byte, []int) { - return file_mgmt_pool_proto_rawDescGZIP(), []int{15, 0} +// Deprecated: Use PoolGetCAReq.ProtoReflect.Descriptor instead. +func (*PoolGetCAReq) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{35} } -func (x *ListPoolsResp_Pool) GetUuid() string { +func (x *PoolGetCAReq) GetSys() string { if x != nil { - return x.Uuid + return x.Sys } return "" } -func (x *ListPoolsResp_Pool) GetLabel() string { +func (x *PoolGetCAReq) GetId() string { if x != nil { - return x.Label + return x.Id } return "" } -func (x *ListPoolsResp_Pool) GetSvcReps() []uint32 { +func (x *PoolGetCAReq) GetSvcRanks() []uint32 { if x != nil { - return x.SvcReps + return x.SvcRanks } return nil } -func (x *ListPoolsResp_Pool) GetState() string { +type PoolGetCAResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + CaBundle []byte `protobuf:"bytes,2,opt,name=ca_bundle,json=caBundle,proto3" json:"ca_bundle,omitempty"` + PoolUuid string `protobuf:"bytes,3,opt,name=pool_uuid,json=poolUuid,proto3" json:"pool_uuid,omitempty"` +} + +func (x *PoolGetCAResp) Reset() { + *x = PoolGetCAResp{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolGetCAResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolGetCAResp) ProtoMessage() {} + +func (x *PoolGetCAResp) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolGetCAResp.ProtoReflect.Descriptor instead. +func (*PoolGetCAResp) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{36} +} + +func (x *PoolGetCAResp) GetStatus() int32 { if x != nil { - return x.State + return x.Status + } + return 0 +} + +func (x *PoolGetCAResp) GetCaBundle() []byte { + if x != nil { + return x.CaBundle + } + return nil +} + +func (x *PoolGetCAResp) GetPoolUuid() string { + if x != nil { + return x.PoolUuid } return "" } -func (x *ListPoolsResp_Pool) GetRebuildState() string { +// PoolAddCAReq appends a CA certificate to the pool's CA bundle. +type PoolAddCAReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sys string `protobuf:"bytes,1,opt,name=sys,proto3" json:"sys,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + CertPem []byte `protobuf:"bytes,3,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"` + SvcRanks []uint32 `protobuf:"varint,4,rep,packed,name=svc_ranks,json=svcRanks,proto3" json:"svc_ranks,omitempty"` + Replace bool `protobuf:"varint,5,opt,name=replace,proto3" json:"replace,omitempty"` // clear existing bundle before append +} + +func (x *PoolAddCAReq) Reset() { + *x = PoolAddCAReq{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolAddCAReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolAddCAReq) ProtoMessage() {} + +func (x *PoolAddCAReq) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolAddCAReq.ProtoReflect.Descriptor instead. +func (*PoolAddCAReq) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{37} +} + +func (x *PoolAddCAReq) GetSys() string { if x != nil { - return x.RebuildState + return x.Sys } return "" } -type ListContResp_Cont struct { +func (x *PoolAddCAReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PoolAddCAReq) GetCertPem() []byte { + if x != nil { + return x.CertPem + } + return nil +} + +func (x *PoolAddCAReq) GetSvcRanks() []uint32 { + if x != nil { + return x.SvcRanks + } + return nil +} + +func (x *PoolAddCAReq) GetReplace() bool { + if x != nil { + return x.Replace + } + return false +} + +type PoolAddCAResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // uuid of container + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + PoolUuid string `protobuf:"bytes,2,opt,name=pool_uuid,json=poolUuid,proto3" json:"pool_uuid,omitempty"` } -func (x *ListContResp_Cont) Reset() { - *x = ListContResp_Cont{} +func (x *PoolAddCAResp) Reset() { + *x = PoolAddCAResp{} if protoimpl.UnsafeEnabled { - mi := &file_mgmt_pool_proto_msgTypes[36] + mi := &file_mgmt_pool_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *ListContResp_Cont) String() string { +func (x *PoolAddCAResp) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ListContResp_Cont) ProtoMessage() {} +func (*PoolAddCAResp) ProtoMessage() {} -func (x *ListContResp_Cont) ProtoReflect() protoreflect.Message { - mi := &file_mgmt_pool_proto_msgTypes[36] +func (x *PoolAddCAResp) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3071,106 +3249,668 @@ func (x *ListContResp_Cont) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ListContResp_Cont.ProtoReflect.Descriptor instead. -func (*ListContResp_Cont) Descriptor() ([]byte, []int) { - return file_mgmt_pool_proto_rawDescGZIP(), []int{17, 0} +// Deprecated: Use PoolAddCAResp.ProtoReflect.Descriptor instead. +func (*PoolAddCAResp) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{38} } -func (x *ListContResp_Cont) GetUuid() string { +func (x *PoolAddCAResp) GetStatus() int32 { if x != nil { - return x.Uuid + return x.Status + } + return 0 +} + +func (x *PoolAddCAResp) GetPoolUuid() string { + if x != nil { + return x.PoolUuid } return "" } -var File_mgmt_pool_proto protoreflect.FileDescriptor +// PoolRemoveCAReq removes one or all CAs from the pool's CA bundle. +type PoolRemoveCAReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -var file_mgmt_pool_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x04, 0x6d, 0x67, 0x6d, 0x74, 0x22, 0xa4, 0x03, 0x0a, 0x0d, 0x50, 0x6f, 0x6f, 0x6c, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x73, 0x79, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x03, 0x61, 0x63, 0x6c, 0x12, 0x32, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x0a, 0x70, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x0c, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x20, 0x0a, - 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x65, 0x70, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x53, 0x76, 0x63, 0x52, 0x65, 0x70, 0x73, 0x12, - 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x01, 0x52, 0x09, 0x74, 0x69, 0x65, 0x72, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, - 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x05, 0x72, 0x61, 0x6e, - 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x22, 0xe7, - 0x01, 0x0a, 0x0e, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x76, 0x63, - 0x5f, 0x6c, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x76, 0x63, 0x4c, - 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x65, 0x70, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x76, 0x63, 0x52, 0x65, 0x70, 0x73, 0x12, 0x1b, 0x0a, - 0x09, 0x74, 0x67, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, - 0x52, 0x08, 0x74, 0x67, 0x74, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, - 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, - 0x74, 0x69, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x65, 0x6d, - 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x27, 0x0a, 0x10, 0x6d, 0x64, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x73, 0x64, 0x5f, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6d, 0x64, 0x4f, 0x6e, 0x53, - 0x73, 0x64, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x0e, 0x50, 0x6f, 0x6f, - 0x6c, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, - 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, - 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, - 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x29, - 0x0a, 0x0f, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x0c, 0x50, 0x6f, - 0x6f, 0x6c, 0x45, 0x76, 0x69, 0x63, 0x74, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x61, 0x6e, 0x64, - 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x23, 0x0a, - 0x0d, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x44, 0x65, 0x73, 0x74, 0x72, - 0x6f, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x3d, 0x0a, 0x0d, - 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x76, 0x69, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0e, - 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, - 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, - 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, - 0x64, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x49, 0x64, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x29, 0x0a, 0x0f, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x22, 0x80, 0x01, 0x0a, 0x0c, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x72, 0x61, 0x69, 0x6e, 0x52, - 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + Sys string `protobuf:"bytes,1,opt,name=sys,proto3" json:"sys,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Fingerprint string `protobuf:"bytes,3,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` // SHA-256 hex of the CA cert to remove + All bool `protobuf:"varint,4,opt,name=all,proto3" json:"all,omitempty"` // remove every CA in the bundle + SvcRanks []uint32 `protobuf:"varint,5,rep,packed,name=svc_ranks,json=svcRanks,proto3" json:"svc_ranks,omitempty"` +} + +func (x *PoolRemoveCAReq) Reset() { + *x = PoolRemoveCAReq{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolRemoveCAReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolRemoveCAReq) ProtoMessage() {} + +func (x *PoolRemoveCAReq) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolRemoveCAReq.ProtoReflect.Descriptor instead. +func (*PoolRemoveCAReq) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{39} +} + +func (x *PoolRemoveCAReq) GetSys() string { + if x != nil { + return x.Sys + } + return "" +} + +func (x *PoolRemoveCAReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PoolRemoveCAReq) GetFingerprint() string { + if x != nil { + return x.Fingerprint + } + return "" +} + +func (x *PoolRemoveCAReq) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +func (x *PoolRemoveCAReq) GetSvcRanks() []uint32 { + if x != nil { + return x.SvcRanks + } + return nil +} + +type PoolRemoveCAResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + CertsRemoved int32 `protobuf:"varint,2,opt,name=certs_removed,json=certsRemoved,proto3" json:"certs_removed,omitempty"` + PoolUuid string `protobuf:"bytes,3,opt,name=pool_uuid,json=poolUuid,proto3" json:"pool_uuid,omitempty"` +} + +func (x *PoolRemoveCAResp) Reset() { + *x = PoolRemoveCAResp{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolRemoveCAResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolRemoveCAResp) ProtoMessage() {} + +func (x *PoolRemoveCAResp) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolRemoveCAResp.ProtoReflect.Descriptor instead. +func (*PoolRemoveCAResp) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{40} +} + +func (x *PoolRemoveCAResp) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *PoolRemoveCAResp) GetCertsRemoved() int32 { + if x != nil { + return x.CertsRemoved + } + return 0 +} + +func (x *PoolRemoveCAResp) GetPoolUuid() string { + if x != nil { + return x.PoolUuid + } + return "" +} + +// PoolGetCertWatermarksReq fetches the per-CN revocation watermarks blob. +type PoolGetCertWatermarksReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sys string `protobuf:"bytes,1,opt,name=sys,proto3" json:"sys,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + SvcRanks []uint32 `protobuf:"varint,3,rep,packed,name=svc_ranks,json=svcRanks,proto3" json:"svc_ranks,omitempty"` +} + +func (x *PoolGetCertWatermarksReq) Reset() { + *x = PoolGetCertWatermarksReq{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolGetCertWatermarksReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolGetCertWatermarksReq) ProtoMessage() {} + +func (x *PoolGetCertWatermarksReq) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolGetCertWatermarksReq.ProtoReflect.Descriptor instead. +func (*PoolGetCertWatermarksReq) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{41} +} + +func (x *PoolGetCertWatermarksReq) GetSys() string { + if x != nil { + return x.Sys + } + return "" +} + +func (x *PoolGetCertWatermarksReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PoolGetCertWatermarksReq) GetSvcRanks() []uint32 { + if x != nil { + return x.SvcRanks + } + return nil +} + +type PoolGetCertWatermarksResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + Watermarks []byte `protobuf:"bytes,2,opt,name=watermarks,proto3" json:"watermarks,omitempty"` // JSON blob, may be empty + PoolUuid string `protobuf:"bytes,3,opt,name=pool_uuid,json=poolUuid,proto3" json:"pool_uuid,omitempty"` +} + +func (x *PoolGetCertWatermarksResp) Reset() { + *x = PoolGetCertWatermarksResp{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolGetCertWatermarksResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolGetCertWatermarksResp) ProtoMessage() {} + +func (x *PoolGetCertWatermarksResp) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolGetCertWatermarksResp.ProtoReflect.Descriptor instead. +func (*PoolGetCertWatermarksResp) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{42} +} + +func (x *PoolGetCertWatermarksResp) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *PoolGetCertWatermarksResp) GetWatermarks() []byte { + if x != nil { + return x.Watermarks + } + return nil +} + +func (x *PoolGetCertWatermarksResp) GetPoolUuid() string { + if x != nil { + return x.PoolUuid + } + return "" +} + +// PoolRevokeClientReq advances the pool's revocation watermark for a CN. +type PoolRevokeClientReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sys string `protobuf:"bytes,1,opt,name=sys,proto3" json:"sys,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Cn string `protobuf:"bytes,3,opt,name=cn,proto3" json:"cn,omitempty"` + SvcRanks []uint32 `protobuf:"varint,4,rep,packed,name=svc_ranks,json=svcRanks,proto3" json:"svc_ranks,omitempty"` + EvictMode PoolRevokeClientReq_EvictMode `protobuf:"varint,5,opt,name=evict_mode,json=evictMode,proto3,enum=mgmt.PoolRevokeClientReq_EvictMode" json:"evict_mode,omitempty"` +} + +func (x *PoolRevokeClientReq) Reset() { + *x = PoolRevokeClientReq{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolRevokeClientReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolRevokeClientReq) ProtoMessage() {} + +func (x *PoolRevokeClientReq) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolRevokeClientReq.ProtoReflect.Descriptor instead. +func (*PoolRevokeClientReq) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{43} +} + +func (x *PoolRevokeClientReq) GetSys() string { + if x != nil { + return x.Sys + } + return "" +} + +func (x *PoolRevokeClientReq) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *PoolRevokeClientReq) GetCn() string { + if x != nil { + return x.Cn + } + return "" +} + +func (x *PoolRevokeClientReq) GetSvcRanks() []uint32 { + if x != nil { + return x.SvcRanks + } + return nil +} + +func (x *PoolRevokeClientReq) GetEvictMode() PoolRevokeClientReq_EvictMode { + if x != nil { + return x.EvictMode + } + return PoolRevokeClientReq_EVICT_DEFAULT +} + +type PoolRevokeClientResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + WatermarkRfc3339 string `protobuf:"bytes,2,opt,name=watermark_rfc3339,json=watermarkRfc3339,proto3" json:"watermark_rfc3339,omitempty"` // committed watermark in RFC3339 UTC + PoolUuid string `protobuf:"bytes,3,opt,name=pool_uuid,json=poolUuid,proto3" json:"pool_uuid,omitempty"` + HandlesEvictedCount int32 `protobuf:"varint,4,opt,name=handles_evicted_count,json=handlesEvictedCount,proto3" json:"handles_evicted_count,omitempty"` + EvictScope string `protobuf:"bytes,5,opt,name=evict_scope,json=evictScope,proto3" json:"evict_scope,omitempty"` // "machine" | "pool" | "none" +} + +func (x *PoolRevokeClientResp) Reset() { + *x = PoolRevokeClientResp{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PoolRevokeClientResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PoolRevokeClientResp) ProtoMessage() {} + +func (x *PoolRevokeClientResp) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PoolRevokeClientResp.ProtoReflect.Descriptor instead. +func (*PoolRevokeClientResp) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{44} +} + +func (x *PoolRevokeClientResp) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *PoolRevokeClientResp) GetWatermarkRfc3339() string { + if x != nil { + return x.WatermarkRfc3339 + } + return "" +} + +func (x *PoolRevokeClientResp) GetPoolUuid() string { + if x != nil { + return x.PoolUuid + } + return "" +} + +func (x *PoolRevokeClientResp) GetHandlesEvictedCount() int32 { + if x != nil { + return x.HandlesEvictedCount + } + return 0 +} + +func (x *PoolRevokeClientResp) GetEvictScope() string { + if x != nil { + return x.EvictScope + } + return "" +} + +type ListPoolsResp_Pool struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // uuid of pool + Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` // pool label + SvcReps []uint32 `protobuf:"varint,3,rep,packed,name=svc_reps,json=svcReps,proto3" json:"svc_reps,omitempty"` // pool service replica ranks + State string `protobuf:"bytes,4,opt,name=state,proto3" json:"state,omitempty"` // pool state + RebuildState string `protobuf:"bytes,5,opt,name=rebuild_state,json=rebuildState,proto3" json:"rebuild_state,omitempty"` // pool rebuild state +} + +func (x *ListPoolsResp_Pool) Reset() { + *x = ListPoolsResp_Pool{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPoolsResp_Pool) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPoolsResp_Pool) ProtoMessage() {} + +func (x *ListPoolsResp_Pool) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPoolsResp_Pool.ProtoReflect.Descriptor instead. +func (*ListPoolsResp_Pool) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{15, 0} +} + +func (x *ListPoolsResp_Pool) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *ListPoolsResp_Pool) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +func (x *ListPoolsResp_Pool) GetSvcReps() []uint32 { + if x != nil { + return x.SvcReps + } + return nil +} + +func (x *ListPoolsResp_Pool) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *ListPoolsResp_Pool) GetRebuildState() string { + if x != nil { + return x.RebuildState + } + return "" +} + +type ListContResp_Cont struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // uuid of container +} + +func (x *ListContResp_Cont) Reset() { + *x = ListContResp_Cont{} + if protoimpl.UnsafeEnabled { + mi := &file_mgmt_pool_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListContResp_Cont) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListContResp_Cont) ProtoMessage() {} + +func (x *ListContResp_Cont) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_pool_proto_msgTypes[46] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListContResp_Cont.ProtoReflect.Descriptor instead. +func (*ListContResp_Cont) Descriptor() ([]byte, []int) { + return file_mgmt_pool_proto_rawDescGZIP(), []int{17, 0} +} + +func (x *ListContResp_Cont) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +var File_mgmt_pool_proto protoreflect.FileDescriptor + +var file_mgmt_pool_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x04, 0x6d, 0x67, 0x6d, 0x74, 0x22, 0xa4, 0x03, 0x0a, 0x0d, 0x50, 0x6f, 0x6f, 0x6c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, + 0x03, 0x73, 0x79, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x03, 0x61, 0x63, 0x6c, 0x12, 0x32, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, + 0x50, 0x6f, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x0a, 0x70, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, + 0x0c, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x20, 0x0a, + 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x65, 0x70, 0x73, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x53, 0x76, 0x63, 0x52, 0x65, 0x70, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x01, 0x52, 0x09, 0x74, 0x69, 0x65, 0x72, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, + 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x05, 0x72, 0x61, 0x6e, + 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x22, 0xe7, + 0x01, 0x0a, 0x0e, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x76, 0x63, + 0x5f, 0x6c, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x76, 0x63, 0x4c, + 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x65, 0x70, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x76, 0x63, 0x52, 0x65, 0x70, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x67, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, + 0x52, 0x08, 0x74, 0x67, 0x74, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x69, + 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, + 0x74, 0x69, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x65, 0x6d, + 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x27, 0x0a, 0x10, 0x6d, 0x64, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x73, 0x64, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6d, 0x64, 0x4f, 0x6e, 0x53, + 0x73, 0x64, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x0e, 0x50, 0x6f, 0x6f, + 0x6c, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, + 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x29, + 0x0a, 0x0f, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x0c, 0x50, 0x6f, + 0x6f, 0x6c, 0x45, 0x76, 0x69, 0x63, 0x74, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, + 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x61, 0x6e, + 0x64, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x23, 0x0a, + 0x0d, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x44, 0x65, 0x73, 0x74, 0x72, + 0x6f, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x3d, 0x0a, 0x0d, + 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x76, 0x69, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0e, + 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, + 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, + 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, + 0x64, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x49, 0x64, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x29, 0x0a, 0x0f, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x78, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x22, 0x80, 0x01, 0x0a, 0x0c, 0x50, 0x6f, 0x6f, 0x6c, 0x44, 0x72, 0x61, 0x69, 0x6e, 0x52, + 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x61, @@ -3436,20 +4176,100 @@ var file_mgmt_pool_proto_rawDesc = []byte{ 0x73, 0x79, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x56, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x2a, 0x25, 0x0a, 0x10, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x07, 0x0a, 0x03, 0x53, 0x43, 0x4d, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x56, 0x4d, 0x45, - 0x10, 0x01, 0x2a, 0x5d, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x01, 0x12, - 0x0e, 0x0a, 0x0a, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, - 0x13, 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x64, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, - 0x04, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x64, 0x61, 0x6f, 0x73, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2f, - 0x73, 0x72, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x22, 0x4d, 0x0a, 0x0c, 0x50, + 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, 0x41, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, + 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x22, 0x61, 0x0a, 0x0d, 0x50, 0x6f, + 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, 0x41, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x61, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x61, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x55, 0x75, 0x69, 0x64, 0x22, 0x82, 0x01, + 0x0a, 0x0c, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x64, 0x43, 0x41, 0x52, 0x65, 0x71, 0x12, 0x10, + 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x70, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x65, 0x72, 0x74, 0x50, 0x65, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x73, + 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, + 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x22, 0x44, 0x0a, 0x0d, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x64, 0x43, 0x41, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x6f, 0x6f, 0x6c, 0x55, 0x75, 0x69, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x0f, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x41, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, + 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, + 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, + 0x6c, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x22, + 0x6c, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x41, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, + 0x65, 0x72, 0x74, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x55, 0x75, 0x69, 0x64, 0x22, 0x59, 0x0a, + 0x18, 0x50, 0x6f, 0x6f, 0x6c, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x57, 0x61, 0x74, 0x65, + 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, + 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, + 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, 0x73, 0x22, 0x70, 0x0a, 0x19, 0x50, 0x6f, 0x6f, 0x6c, + 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0a, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x55, 0x75, 0x69, 0x64, 0x22, 0xed, 0x01, 0x0a, 0x13, 0x50, + 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x73, 0x79, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x63, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x76, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x6b, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x76, 0x63, 0x52, 0x61, 0x6e, 0x6b, + 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x65, 0x76, 0x69, 0x63, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x2e, 0x45, 0x76, 0x69, 0x63, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x09, 0x65, 0x76, 0x69, 0x63, + 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x43, 0x0a, 0x09, 0x45, 0x76, 0x69, 0x63, 0x74, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x56, 0x49, 0x43, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x56, 0x49, 0x43, 0x54, 0x5f, 0x50, + 0x4f, 0x4f, 0x4c, 0x5f, 0x57, 0x49, 0x44, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x56, + 0x49, 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x22, 0xcd, 0x01, 0x0a, 0x14, 0x50, + 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x77, + 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x72, 0x66, 0x63, 0x33, 0x33, 0x33, 0x39, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, + 0x6b, 0x52, 0x66, 0x63, 0x33, 0x33, 0x33, 0x39, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, + 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6f, + 0x6c, 0x55, 0x75, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, + 0x5f, 0x65, 0x76, 0x69, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x45, 0x76, 0x69, + 0x63, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x76, 0x69, + 0x63, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x65, 0x76, 0x69, 0x63, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x2a, 0x25, 0x0a, 0x10, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, + 0x0a, 0x03, 0x53, 0x43, 0x4d, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x56, 0x4d, 0x45, 0x10, + 0x01, 0x2a, 0x5d, 0x0a, 0x10, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6e, + 0x67, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x01, 0x12, 0x0e, + 0x0a, 0x0a, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x13, + 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x64, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x04, + 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, + 0x61, 0x6f, 0x73, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2f, 0x73, + 0x72, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3464,73 +4284,85 @@ func file_mgmt_pool_proto_rawDescGZIP() []byte { return file_mgmt_pool_proto_rawDescData } -var file_mgmt_pool_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_mgmt_pool_proto_msgTypes = make([]protoimpl.MessageInfo, 37) +var file_mgmt_pool_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_mgmt_pool_proto_msgTypes = make([]protoimpl.MessageInfo, 47) var file_mgmt_pool_proto_goTypes = []interface{}{ (StorageMediaType)(0), // 0: mgmt.StorageMediaType (PoolServiceState)(0), // 1: mgmt.PoolServiceState (PoolRebuildStatus_State)(0), // 2: mgmt.PoolRebuildStatus.State (PoolQueryTargetInfo_TargetState)(0), // 3: mgmt.PoolQueryTargetInfo.TargetState - (*PoolCreateReq)(nil), // 4: mgmt.PoolCreateReq - (*PoolCreateResp)(nil), // 5: mgmt.PoolCreateResp - (*PoolDestroyReq)(nil), // 6: mgmt.PoolDestroyReq - (*PoolDestroyResp)(nil), // 7: mgmt.PoolDestroyResp - (*PoolEvictReq)(nil), // 8: mgmt.PoolEvictReq - (*PoolEvictResp)(nil), // 9: mgmt.PoolEvictResp - (*PoolExcludeReq)(nil), // 10: mgmt.PoolExcludeReq - (*PoolExcludeResp)(nil), // 11: mgmt.PoolExcludeResp - (*PoolDrainReq)(nil), // 12: mgmt.PoolDrainReq - (*PoolDrainResp)(nil), // 13: mgmt.PoolDrainResp - (*PoolExtendReq)(nil), // 14: mgmt.PoolExtendReq - (*PoolExtendResp)(nil), // 15: mgmt.PoolExtendResp - (*PoolReintReq)(nil), // 16: mgmt.PoolReintReq - (*PoolReintResp)(nil), // 17: mgmt.PoolReintResp - (*ListPoolsReq)(nil), // 18: mgmt.ListPoolsReq - (*ListPoolsResp)(nil), // 19: mgmt.ListPoolsResp - (*ListContReq)(nil), // 20: mgmt.ListContReq - (*ListContResp)(nil), // 21: mgmt.ListContResp - (*PoolQueryReq)(nil), // 22: mgmt.PoolQueryReq - (*StorageUsageStats)(nil), // 23: mgmt.StorageUsageStats - (*PoolRebuildStatus)(nil), // 24: mgmt.PoolRebuildStatus - (*PoolQueryResp)(nil), // 25: mgmt.PoolQueryResp - (*PoolProperty)(nil), // 26: mgmt.PoolProperty - (*PoolSetPropReq)(nil), // 27: mgmt.PoolSetPropReq - (*PoolSetPropResp)(nil), // 28: mgmt.PoolSetPropResp - (*PoolGetPropReq)(nil), // 29: mgmt.PoolGetPropReq - (*PoolGetPropResp)(nil), // 30: mgmt.PoolGetPropResp - (*PoolUpgradeReq)(nil), // 31: mgmt.PoolUpgradeReq - (*PoolQueryTargetReq)(nil), // 32: mgmt.PoolQueryTargetReq - (*StorageTargetUsage)(nil), // 33: mgmt.StorageTargetUsage - (*PoolQueryTargetInfo)(nil), // 34: mgmt.PoolQueryTargetInfo - (*PoolQueryTargetResp)(nil), // 35: mgmt.PoolQueryTargetResp - (*PoolRebuildStartReq)(nil), // 36: mgmt.PoolRebuildStartReq - (*PoolRebuildStopReq)(nil), // 37: mgmt.PoolRebuildStopReq - (*PoolSelfHealEvalReq)(nil), // 38: mgmt.PoolSelfHealEvalReq - (*ListPoolsResp_Pool)(nil), // 39: mgmt.ListPoolsResp.Pool - (*ListContResp_Cont)(nil), // 40: mgmt.ListContResp.Cont + (PoolRevokeClientReq_EvictMode)(0), // 4: mgmt.PoolRevokeClientReq.EvictMode + (*PoolCreateReq)(nil), // 5: mgmt.PoolCreateReq + (*PoolCreateResp)(nil), // 6: mgmt.PoolCreateResp + (*PoolDestroyReq)(nil), // 7: mgmt.PoolDestroyReq + (*PoolDestroyResp)(nil), // 8: mgmt.PoolDestroyResp + (*PoolEvictReq)(nil), // 9: mgmt.PoolEvictReq + (*PoolEvictResp)(nil), // 10: mgmt.PoolEvictResp + (*PoolExcludeReq)(nil), // 11: mgmt.PoolExcludeReq + (*PoolExcludeResp)(nil), // 12: mgmt.PoolExcludeResp + (*PoolDrainReq)(nil), // 13: mgmt.PoolDrainReq + (*PoolDrainResp)(nil), // 14: mgmt.PoolDrainResp + (*PoolExtendReq)(nil), // 15: mgmt.PoolExtendReq + (*PoolExtendResp)(nil), // 16: mgmt.PoolExtendResp + (*PoolReintReq)(nil), // 17: mgmt.PoolReintReq + (*PoolReintResp)(nil), // 18: mgmt.PoolReintResp + (*ListPoolsReq)(nil), // 19: mgmt.ListPoolsReq + (*ListPoolsResp)(nil), // 20: mgmt.ListPoolsResp + (*ListContReq)(nil), // 21: mgmt.ListContReq + (*ListContResp)(nil), // 22: mgmt.ListContResp + (*PoolQueryReq)(nil), // 23: mgmt.PoolQueryReq + (*StorageUsageStats)(nil), // 24: mgmt.StorageUsageStats + (*PoolRebuildStatus)(nil), // 25: mgmt.PoolRebuildStatus + (*PoolQueryResp)(nil), // 26: mgmt.PoolQueryResp + (*PoolProperty)(nil), // 27: mgmt.PoolProperty + (*PoolSetPropReq)(nil), // 28: mgmt.PoolSetPropReq + (*PoolSetPropResp)(nil), // 29: mgmt.PoolSetPropResp + (*PoolGetPropReq)(nil), // 30: mgmt.PoolGetPropReq + (*PoolGetPropResp)(nil), // 31: mgmt.PoolGetPropResp + (*PoolUpgradeReq)(nil), // 32: mgmt.PoolUpgradeReq + (*PoolQueryTargetReq)(nil), // 33: mgmt.PoolQueryTargetReq + (*StorageTargetUsage)(nil), // 34: mgmt.StorageTargetUsage + (*PoolQueryTargetInfo)(nil), // 35: mgmt.PoolQueryTargetInfo + (*PoolQueryTargetResp)(nil), // 36: mgmt.PoolQueryTargetResp + (*PoolRebuildStartReq)(nil), // 37: mgmt.PoolRebuildStartReq + (*PoolRebuildStopReq)(nil), // 38: mgmt.PoolRebuildStopReq + (*PoolSelfHealEvalReq)(nil), // 39: mgmt.PoolSelfHealEvalReq + (*PoolGetCAReq)(nil), // 40: mgmt.PoolGetCAReq + (*PoolGetCAResp)(nil), // 41: mgmt.PoolGetCAResp + (*PoolAddCAReq)(nil), // 42: mgmt.PoolAddCAReq + (*PoolAddCAResp)(nil), // 43: mgmt.PoolAddCAResp + (*PoolRemoveCAReq)(nil), // 44: mgmt.PoolRemoveCAReq + (*PoolRemoveCAResp)(nil), // 45: mgmt.PoolRemoveCAResp + (*PoolGetCertWatermarksReq)(nil), // 46: mgmt.PoolGetCertWatermarksReq + (*PoolGetCertWatermarksResp)(nil), // 47: mgmt.PoolGetCertWatermarksResp + (*PoolRevokeClientReq)(nil), // 48: mgmt.PoolRevokeClientReq + (*PoolRevokeClientResp)(nil), // 49: mgmt.PoolRevokeClientResp + (*ListPoolsResp_Pool)(nil), // 50: mgmt.ListPoolsResp.Pool + (*ListContResp_Cont)(nil), // 51: mgmt.ListContResp.Cont } var file_mgmt_pool_proto_depIdxs = []int32{ - 26, // 0: mgmt.PoolCreateReq.properties:type_name -> mgmt.PoolProperty - 39, // 1: mgmt.ListPoolsResp.pools:type_name -> mgmt.ListPoolsResp.Pool - 40, // 2: mgmt.ListContResp.containers:type_name -> mgmt.ListContResp.Cont + 27, // 0: mgmt.PoolCreateReq.properties:type_name -> mgmt.PoolProperty + 50, // 1: mgmt.ListPoolsResp.pools:type_name -> mgmt.ListPoolsResp.Pool + 51, // 2: mgmt.ListContResp.containers:type_name -> mgmt.ListContResp.Cont 0, // 3: mgmt.StorageUsageStats.media_type:type_name -> mgmt.StorageMediaType 2, // 4: mgmt.PoolRebuildStatus.state:type_name -> mgmt.PoolRebuildStatus.State 2, // 5: mgmt.PoolRebuildStatus.derived_state:type_name -> mgmt.PoolRebuildStatus.State - 24, // 6: mgmt.PoolQueryResp.rebuild:type_name -> mgmt.PoolRebuildStatus - 23, // 7: mgmt.PoolQueryResp.tier_stats:type_name -> mgmt.StorageUsageStats + 25, // 6: mgmt.PoolQueryResp.rebuild:type_name -> mgmt.PoolRebuildStatus + 24, // 7: mgmt.PoolQueryResp.tier_stats:type_name -> mgmt.StorageUsageStats 1, // 8: mgmt.PoolQueryResp.state:type_name -> mgmt.PoolServiceState - 26, // 9: mgmt.PoolSetPropReq.properties:type_name -> mgmt.PoolProperty - 26, // 10: mgmt.PoolGetPropReq.properties:type_name -> mgmt.PoolProperty - 26, // 11: mgmt.PoolGetPropResp.properties:type_name -> mgmt.PoolProperty + 27, // 9: mgmt.PoolSetPropReq.properties:type_name -> mgmt.PoolProperty + 27, // 10: mgmt.PoolGetPropReq.properties:type_name -> mgmt.PoolProperty + 27, // 11: mgmt.PoolGetPropResp.properties:type_name -> mgmt.PoolProperty 0, // 12: mgmt.StorageTargetUsage.media_type:type_name -> mgmt.StorageMediaType 3, // 13: mgmt.PoolQueryTargetInfo.state:type_name -> mgmt.PoolQueryTargetInfo.TargetState - 33, // 14: mgmt.PoolQueryTargetInfo.space:type_name -> mgmt.StorageTargetUsage - 34, // 15: mgmt.PoolQueryTargetResp.infos:type_name -> mgmt.PoolQueryTargetInfo - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 34, // 14: mgmt.PoolQueryTargetInfo.space:type_name -> mgmt.StorageTargetUsage + 35, // 15: mgmt.PoolQueryTargetResp.infos:type_name -> mgmt.PoolQueryTargetInfo + 4, // 16: mgmt.PoolRevokeClientReq.evict_mode:type_name -> mgmt.PoolRevokeClientReq.EvictMode + 17, // [17:17] is the sub-list for method output_type + 17, // [17:17] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_mgmt_pool_proto_init() } @@ -3960,7 +4792,7 @@ func file_mgmt_pool_proto_init() { } } file_mgmt_pool_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPoolsResp_Pool); i { + switch v := v.(*PoolGetCAReq); i { case 0: return &v.state case 1: @@ -3972,6 +4804,126 @@ func file_mgmt_pool_proto_init() { } } file_mgmt_pool_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolGetCAResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolAddCAReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolAddCAResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolRemoveCAReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolRemoveCAResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolGetCertWatermarksReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolGetCertWatermarksResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolRevokeClientReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PoolRevokeClientResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPoolsResp_Pool); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mgmt_pool_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListContResp_Cont); i { case 0: return &v.state @@ -3994,8 +4946,8 @@ func file_mgmt_pool_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_mgmt_pool_proto_rawDesc, - NumEnums: 4, - NumMessages: 37, + NumEnums: 5, + NumMessages: 47, NumExtensions: 0, NumServices: 0, }, diff --git a/src/control/lib/control/pool_cert.go b/src/control/lib/control/pool_cert.go new file mode 100644 index 00000000000..7f90ae25eb5 --- /dev/null +++ b/src/control/lib/control/pool_cert.go @@ -0,0 +1,641 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package control + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + + pbUtil "github.com/daos-stack/daos/src/control/common/proto" + mgmtpb "github.com/daos-stack/daos/src/control/common/proto/mgmt" + "github.com/daos-stack/daos/src/control/security" +) + +// PoolSetupCertAuthReq contains the parameters for setting up +// certificate-based authentication on a pool. +type PoolSetupCertAuthReq struct { + poolRequest + ID string // pool UUID or label + + // For generate mode: provide both. + DaosCACertPath string // path to DAOS CA certificate + DaosCAKeyPath string // path to DAOS CA private key + + // For import mode: provide CertPEM instead. + CertPEM []byte // PEM-encoded pool CA cert to import + + // Replace clears any existing CA bundle before installing the new cert. + Replace bool +} + +// PoolSetupCertAuthResp contains the result of setting up cert auth. +type PoolSetupCertAuthResp struct { + PoolUUID string + CACertPEM []byte // PEM-encoded pool CA certificate + CAKeyPEM []byte // PEM-encoded pool CA private key (empty for import mode) +} + +// PoolSetupCertAuth installs a pool intermediate CA, generating a fresh +// ECDSA P-384 CA signed by the DAOS root unless CertPEM is supplied. +func PoolSetupCertAuth(ctx context.Context, rpcClient UnaryInvoker, req *PoolSetupCertAuthReq) (*PoolSetupCertAuthResp, error) { + var certPEM, keyPEM []byte + + if len(req.CertPEM) > 0 { + cert, err := parsePEMCACert(req.CertPEM) + if err != nil { + return nil, err + } + if req.DaosCACertPath != "" { + if err := verifyCertChain(req.DaosCACertPath, cert); err != nil { + return nil, errors.Wrap(err, "pool CA does not chain to DAOS CA") + } + } + certPEM = req.CertPEM + } else { + if req.DaosCACertPath == "" || req.DaosCAKeyPath == "" { + return nil, errors.New("DaosCACertPath and DaosCAKeyPath are required for generate mode") + } + + poolResp, err := PoolQuery(ctx, rpcClient, &PoolQueryReq{ID: req.ID}) + if err != nil { + return nil, errors.Wrap(err, "resolving pool UUID") + } + poolUUID := poolResp.UUID.String() + + daosCACert, err := security.LoadCertificate(req.DaosCACertPath) + if err != nil { + return nil, errors.Wrap(err, "loading DAOS CA certificate") + } + daosCAKey, err := security.LoadPrivateKey(req.DaosCAKeyPath) + if err != nil { + return nil, errors.Wrap(err, "loading DAOS CA private key") + } + + certPEM, keyPEM, err = generatePoolCA(poolUUID, daosCACert, daosCAKey) + if err != nil { + return nil, err + } + } + + addResp, err := PoolAddCA(ctx, rpcClient, &PoolAddCAReq{ + ID: req.ID, + Replace: req.Replace, + CertPEM: certPEM, + }) + if err != nil { + return nil, errors.Wrap(err, "adding pool CA") + } + + return &PoolSetupCertAuthResp{ + PoolUUID: addResp.PoolUUID, + CACertPEM: certPEM, + CAKeyPEM: keyPEM, + }, nil +} + +// PoolGenerateClientCertsReq contains the parameters for generating +// client certificates signed by a pool's CA. +type PoolGenerateClientCertsReq struct { + CAKeyPath string + Nodes []string // CN = node: + Tenants []string // CN = tenant:; mutually exclusive with Nodes +} + +// ClientCert contains the generated certificate and key for a client. +type ClientCert struct { + Name string // the node or tenant name (without prefix) + CN string // the full CN (with prefix) + CertPEM []byte + KeyPEM []byte +} + +// PoolGenerateClientCerts generates certificates signed by a pool CA. +// This is a local crypto operation — no RPC is needed. +func PoolGenerateClientCerts(req *PoolGenerateClientCertsReq) ([]*ClientCert, error) { + if len(req.Nodes) == 0 && len(req.Tenants) == 0 { + return nil, errors.New("specify Nodes or Tenants") + } + if len(req.Nodes) > 0 && len(req.Tenants) > 0 { + return nil, errors.New("Nodes and Tenants are mutually exclusive") + } + + caCert, caKey, err := loadCertAndKey(req.CAKeyPath) + if err != nil { + return nil, errors.Wrap(err, "loading pool CA") + } + + type target struct { + name string + cn string + } + var targets []target + for _, n := range req.Nodes { + targets = append(targets, target{name: n, cn: security.CertCNPrefixNode + n}) + } + for _, t := range req.Tenants { + targets = append(targets, target{name: t, cn: security.CertCNPrefixTenant + t}) + } + + var results []*ClientCert + for _, tgt := range targets { + certPEM, keyPEM, err := generateClientCert(tgt.cn, caCert, caKey) + if err != nil { + return nil, errors.Wrapf(err, "generating cert for %s", tgt.cn) + } + results = append(results, &ClientCert{ + Name: tgt.name, + CN: tgt.cn, + CertPEM: certPEM, + KeyPEM: keyPEM, + }) + } + + return results, nil +} + +// generatePoolCA creates a pool-specific intermediate CA key pair signed +// by the DAOS CA. +func generatePoolCA(poolUUID string, daosCACert *x509.Certificate, daosCAKey interface{}) (certPEM, keyPEM []byte, err error) { + poolCAKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, nil, errors.Wrap(err, "generating pool CA key") + } + + serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return nil, nil, errors.Wrap(err, "generating serial number") + } + + now := time.Now() + template := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: fmt.Sprintf("DAOS Pool CA %s", poolUUID), + Organization: []string{"DAOS"}, + }, + NotBefore: now, + NotAfter: now.Add(365 * 24 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + MaxPathLen: 0, + MaxPathLenZero: true, + } + + certDER, err := x509.CreateCertificate(rand.Reader, template, daosCACert, &poolCAKey.PublicKey, daosCAKey) + if err != nil { + return nil, nil, errors.Wrap(err, "creating pool CA certificate") + } + + certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) + + keyDER, err := x509.MarshalPKCS8PrivateKey(poolCAKey) + if err != nil { + return nil, nil, errors.Wrap(err, "marshaling pool CA key") + } + keyPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}) + + return certPEM, keyPEM, nil +} + +// generateClientCert creates a client certificate signed by a pool CA. +// NotBefore is set to the current time. +func generateClientCert(cn string, caCert *x509.Certificate, caKey interface{}) (certPEM, keyPEM []byte, err error) { + return generateClientCertAt(cn, caCert, caKey, time.Now().UTC()) +} + +// generateClientCertAt creates a client cert with an explicit NotBefore. +func generateClientCertAt(cn string, caCert *x509.Certificate, caKey interface{}, notBefore time.Time) (certPEM, keyPEM []byte, err error) { + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, nil, errors.Wrap(err, "generating key") + } + + serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return nil, nil, errors.Wrap(err, "generating serial number") + } + + template := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: cn, + Organization: []string{"DAOS"}, + }, + NotBefore: notBefore, + NotAfter: notBefore.Add(365 * 24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{ + x509.ExtKeyUsageClientAuth, + }, + } + + certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, &key.PublicKey, caKey) + if err != nil { + return nil, nil, errors.Wrap(err, "creating certificate") + } + + certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) + + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + return nil, nil, errors.Wrap(err, "marshaling key") + } + keyPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}) + + return certPEM, keyPEM, nil +} + +// parsePEMCACert parses a PEM-encoded certificate and validates it is a CA. +func parsePEMCACert(certPEM []byte) (*x509.Certificate, error) { + block, _ := pem.Decode(certPEM) + if block == nil || block.Type != "CERTIFICATE" { + return nil, errors.New("invalid PEM certificate") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, errors.Wrap(err, "parsing certificate") + } + if !cert.IsCA { + return nil, errors.New("certificate is not a CA") + } + return cert, nil +} + +// verifyCertChain verifies that cert chains to the CA at caCertPath. +func verifyCertChain(caCertPath string, cert *x509.Certificate) error { + caCert, err := security.LoadCertificate(caCertPath) + if err != nil { + return errors.Wrap(err, "loading CA certificate") + } + + roots := x509.NewCertPool() + roots.AddCert(caCert) + + _, err = cert.Verify(x509.VerifyOptions{ + Roots: roots, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, + }) + return err +} + +// loadCertAndKey loads a key and its sibling .crt (stripping any extension). +func loadCertAndKey(keyPath string) (*x509.Certificate, interface{}, error) { + if keyPath == "" { + return nil, nil, errors.New("key path is empty") + } + base := strings.TrimSuffix(keyPath, filepath.Ext(keyPath)) + certPath := base + ".crt" + + cert, err := security.LoadCertificate(certPath) + if err != nil { + return nil, nil, errors.Wrap(err, "loading certificate") + } + + key, err := security.LoadPrivateKey(keyPath) + if err != nil { + return nil, nil, errors.Wrap(err, "loading private key") + } + + return cert, key, nil +} + +// PoolGetCAReq contains pool get-CA parameters. +type PoolGetCAReq struct { + poolRequest + ID string // pool UUID or label +} + +// PoolGetCAResp carries the pool's CA bundle and the parsed cert summary. +type PoolGetCAResp struct { + PoolUUID string + PEM []byte + Certs []security.PoolCertInfo +} + +// PoolGetCA returns the pool's CA bundle. +func PoolGetCA(ctx context.Context, rpcClient UnaryInvoker, req *PoolGetCAReq) (*PoolGetCAResp, error) { + if req == nil { + return nil, errors.New("nil PoolGetCAReq") + } + pbReq := &mgmtpb.PoolGetCAReq{ + Sys: req.getSystem(rpcClient), + Id: req.ID, + } + req.setRPC(func(ctx context.Context, conn *grpc.ClientConn) (proto.Message, error) { + return mgmtpb.NewMgmtSvcClient(conn).PoolGetCA(ctx, pbReq) + }) + ur, err := rpcClient.InvokeUnaryRPC(ctx, req) + if err != nil { + return nil, err + } + if err := ur.getMSError(); err != nil { + return nil, errors.Wrap(err, "pool get-CA failed") + } + msResp, err := ur.getMSResponse() + if err != nil { + return nil, errors.Wrap(err, "pool get-CA response") + } + pbResp, ok := msResp.(*mgmtpb.PoolGetCAResp) + if !ok { + return nil, errors.Errorf("unexpected response type %T", msResp) + } + resp := &PoolGetCAResp{ + PoolUUID: pbResp.GetPoolUuid(), + PEM: pbResp.GetCaBundle(), + } + if len(resp.PEM) > 0 { + resp.Certs, err = security.ParseCABundle(resp.PEM) + if err != nil { + return nil, errors.Wrap(err, "parsing pool CA bundle") + } + } + return resp, nil +} + +// PoolAddCAReq contains pool add-CA parameters. +type PoolAddCAReq struct { + poolRequest + ID string // pool UUID or label + CertPEM []byte // PEM-encoded CA certificate to append + Replace bool // clear existing bundle before append +} + +// PoolAddCAResp carries the result of a PoolAddCA call. +type PoolAddCAResp struct { + PoolUUID string +} + +// PoolAddCA appends a CA cert to the pool's CA bundle. +func PoolAddCA(ctx context.Context, rpcClient UnaryInvoker, req *PoolAddCAReq) (*PoolAddCAResp, error) { + if req == nil { + return nil, errors.New("nil PoolAddCAReq") + } + if len(req.CertPEM) == 0 { + return nil, errors.New("CertPEM is empty") + } + + pbReq := &mgmtpb.PoolAddCAReq{ + Sys: req.getSystem(rpcClient), + Id: req.ID, + CertPem: req.CertPEM, + Replace: req.Replace, + } + req.setRPC(func(ctx context.Context, conn *grpc.ClientConn) (proto.Message, error) { + return mgmtpb.NewMgmtSvcClient(conn).PoolAddCA(ctx, pbReq) + }) + + rpcClient.Debugf("DAOS pool add-CA request: %s\n", pbUtil.Debug(pbReq)) + ur, err := rpcClient.InvokeUnaryRPC(ctx, req) + if err != nil { + return nil, err + } + if err := ur.getMSError(); err != nil { + return nil, errors.Wrap(err, "pool add-CA failed") + } + msResp, err := ur.getMSResponse() + if err != nil { + return nil, errors.Wrap(err, "pool add-CA response") + } + pbResp, ok := msResp.(*mgmtpb.PoolAddCAResp) + if !ok { + return nil, errors.Errorf("unexpected response type %T", msResp) + } + return &PoolAddCAResp{PoolUUID: pbResp.GetPoolUuid()}, nil +} + +// PoolRemoveCAReq contains pool remove-CA parameters. +type PoolRemoveCAReq struct { + poolRequest + ID string // pool UUID or label + Fingerprint string // SHA-256 fingerprint (hex) of CA to remove; empty with All + All bool // if true, clear the entire CA bundle +} + +// PoolRemoveCAResp contains the result of a remove-CA operation. +type PoolRemoveCAResp struct { + PoolUUID string + CertsRemoved int +} + +// PoolRemoveCA removes one (by Fingerprint) or all CAs from the pool bundle. +func PoolRemoveCA(ctx context.Context, rpcClient UnaryInvoker, req *PoolRemoveCAReq) (*PoolRemoveCAResp, error) { + if req == nil { + return nil, errors.New("nil PoolRemoveCAReq") + } + if !req.All && req.Fingerprint == "" { + return nil, errors.New("specify Fingerprint or All") + } + if req.All && req.Fingerprint != "" { + return nil, errors.New("Fingerprint and All are mutually exclusive") + } + + pbReq := &mgmtpb.PoolRemoveCAReq{ + Sys: req.getSystem(rpcClient), + Id: req.ID, + Fingerprint: req.Fingerprint, + All: req.All, + } + req.setRPC(func(ctx context.Context, conn *grpc.ClientConn) (proto.Message, error) { + return mgmtpb.NewMgmtSvcClient(conn).PoolRemoveCA(ctx, pbReq) + }) + + rpcClient.Debugf("DAOS pool remove-CA request: %s\n", pbUtil.Debug(pbReq)) + ur, err := rpcClient.InvokeUnaryRPC(ctx, req) + if err != nil { + return nil, err + } + if err := ur.getMSError(); err != nil { + return nil, errors.Wrap(err, "pool remove-CA failed") + } + + msResp, err := ur.getMSResponse() + if err != nil { + return nil, errors.Wrap(err, "pool remove-CA response") + } + pbResp, ok := msResp.(*mgmtpb.PoolRemoveCAResp) + if !ok { + return nil, errors.Errorf("unexpected response type %T", msResp) + } + + return &PoolRemoveCAResp{ + PoolUUID: pbResp.GetPoolUuid(), + CertsRemoved: int(pbResp.GetCertsRemoved()), + }, nil +} + +// PoolGetCertWatermarksReq contains pool get-cert-watermarks parameters. +type PoolGetCertWatermarksReq struct { + poolRequest + ID string // pool UUID or label +} + +// PoolGetCertWatermarks returns the pool's per-CN revocation watermarks. +func PoolGetCertWatermarks(ctx context.Context, rpcClient UnaryInvoker, req *PoolGetCertWatermarksReq) (security.CertWatermarks, error) { + if req == nil { + return nil, errors.New("nil PoolGetCertWatermarksReq") + } + pbReq := &mgmtpb.PoolGetCertWatermarksReq{ + Sys: req.getSystem(rpcClient), + Id: req.ID, + } + req.setRPC(func(ctx context.Context, conn *grpc.ClientConn) (proto.Message, error) { + return mgmtpb.NewMgmtSvcClient(conn).PoolGetCertWatermarks(ctx, pbReq) + }) + ur, err := rpcClient.InvokeUnaryRPC(ctx, req) + if err != nil { + return nil, err + } + if err := ur.getMSError(); err != nil { + return nil, errors.Wrap(err, "pool get-cert-watermarks failed") + } + msResp, err := ur.getMSResponse() + if err != nil { + return nil, errors.Wrap(err, "pool get-cert-watermarks response") + } + pbResp, ok := msResp.(*mgmtpb.PoolGetCertWatermarksResp) + if !ok { + return nil, errors.Errorf("unexpected response type %T", msResp) + } + if len(pbResp.GetWatermarks()) == 0 { + return nil, nil + } + return security.DecodeCertWatermarks(pbResp.GetWatermarks()) +} + +// PoolRevokeEvictMode controls how PoolRevokeClient evicts active handles. +type PoolRevokeEvictMode int + +const ( + // PoolRevokeEvictDefault uses per-machine evict for node:X, pool-wide for tenant:X. + PoolRevokeEvictDefault PoolRevokeEvictMode = iota + // PoolRevokeEvictPoolWide evicts all handles on the pool. + PoolRevokeEvictPoolWide + // PoolRevokeEvictNone leaves active handles alone. + PoolRevokeEvictNone +) + +// PoolRevokeClientReq contains pool revoke-client parameters. +type PoolRevokeClientReq struct { + poolRequest + ID string // pool UUID or label + CAKeyPath string // path to the pool CA private key + Node string // node name to revoke (mutually exclusive with Tenant) + Tenant string // tenant name to revoke (mutually exclusive with Node) + EvictMode PoolRevokeEvictMode // how to evict active handles +} + +// RevokedClientCert is the fresh replacement cert+key produced by a +// revoke-client invocation. +type RevokedClientCert struct { + Name string // the node or tenant name (without prefix) + CN string // the full CN (with prefix) + CertPEM []byte + KeyPEM []byte +} + +// PoolRevokeClientResp contains the result of a revoke-client operation. +type PoolRevokeClientResp struct { + PoolUUID string + Cert *RevokedClientCert + Watermark time.Time // certs at or before this NotBefore are revoked + HandlesEvicted int32 // number of active handles evicted + EvictScope string // "machine" | "pool" | "none" +} + +// PoolRevokeClient advances the pool's per-CN revocation watermark +// and signs a replacement cert with NotBefore strictly past the +// committed watermark. +func PoolRevokeClient(ctx context.Context, rpcClient UnaryInvoker, req *PoolRevokeClientReq) (*PoolRevokeClientResp, error) { + if req == nil { + return nil, errors.New("nil PoolRevokeClientReq") + } + if req.CAKeyPath == "" { + return nil, errors.New("CAKeyPath is required") + } + if (req.Node == "") == (req.Tenant == "") { + return nil, errors.New("specify exactly one of Node or Tenant") + } + + name := req.Node + cn := security.CertCNPrefixNode + req.Node + if req.Tenant != "" { + name = req.Tenant + cn = security.CertCNPrefixTenant + req.Tenant + } + + pbReq := &mgmtpb.PoolRevokeClientReq{ + Sys: req.getSystem(rpcClient), + Id: req.ID, + Cn: cn, + EvictMode: mgmtpb.PoolRevokeClientReq_EvictMode(req.EvictMode), + } + req.setRPC(func(ctx context.Context, conn *grpc.ClientConn) (proto.Message, error) { + return mgmtpb.NewMgmtSvcClient(conn).PoolRevokeClient(ctx, pbReq) + }) + + rpcClient.Debugf("DAOS pool revoke-client request: %s\n", pbUtil.Debug(pbReq)) + ur, err := rpcClient.InvokeUnaryRPC(ctx, req) + if err != nil { + return nil, err + } + if err := ur.getMSError(); err != nil { + return nil, errors.Wrap(err, "pool revoke-client failed") + } + + msResp, err := ur.getMSResponse() + if err != nil { + return nil, errors.Wrap(err, "pool revoke-client response") + } + pbResp, ok := msResp.(*mgmtpb.PoolRevokeClientResp) + if !ok { + return nil, errors.Errorf("unexpected response type %T", msResp) + } + + watermark, err := time.Parse(time.RFC3339, pbResp.GetWatermarkRfc3339()) + if err != nil { + return nil, errors.Wrap(err, "parsing committed watermark") + } + watermark = watermark.UTC() + + caCert, caKey, err := loadCertAndKey(req.CAKeyPath) + if err != nil { + return nil, errors.Wrap(err, "loading pool CA") + } + + certPEM, keyPEM, err := generateClientCertAt(cn, caCert, caKey, watermark.Add(time.Second)) + if err != nil { + return nil, errors.Wrapf(err, "generating replacement cert for %s", cn) + } + + return &PoolRevokeClientResp{ + PoolUUID: pbResp.GetPoolUuid(), + Cert: &RevokedClientCert{ + Name: name, + CN: cn, + CertPEM: certPEM, + KeyPEM: keyPEM, + }, + Watermark: watermark, + HandlesEvicted: pbResp.GetHandlesEvictedCount(), + EvictScope: pbResp.GetEvictScope(), + }, nil +} diff --git a/src/control/lib/daos/drpc.go b/src/control/lib/daos/drpc.go index 876c19797c3..91ff6515c39 100644 --- a/src/control/lib/daos/drpc.go +++ b/src/control/lib/daos/drpc.go @@ -1,6 +1,6 @@ // // (C) Copyright 2019-2024 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -290,6 +290,7 @@ func (m securityMethod) ID() int32 { func (m securityMethod) String() string { if s, ok := map[securityMethod]string{ MethodValidateCredentials: "validate credentials", + MethodValidateNodeCert: "validate node cert", }[m]; ok { return s } @@ -300,4 +301,6 @@ func (m securityMethod) String() string { const ( // MethodValidateCredentials is a ModuleSecurity method MethodValidateCredentials securityMethod = C.DRPC_METHOD_SEC_VALIDATE_CREDS + // MethodValidateNodeCert is a ModuleSecurity method for per-pool node cert validation + MethodValidateNodeCert securityMethod = C.DRPC_METHOD_SEC_VALIDATE_NODE_CERT ) diff --git a/src/control/lib/daos/pool_property.go b/src/control/lib/daos/pool_property.go index dacebe794d4..106232675cb 100644 --- a/src/control/lib/daos/pool_property.go +++ b/src/control/lib/daos/pool_property.go @@ -96,6 +96,10 @@ const ( PoolPropertyReintMode = C.DAOS_PROP_PO_REINT_MODE PoolPropertySvcOpsEnabled = C.DAOS_PROP_PO_SVC_OPS_ENABLED PoolPropertySvcOpsEntryAge = C.DAOS_PROP_PO_SVC_OPS_ENTRY_AGE + // PoolPropertyPoolCA is the PEM intermediate CA for per-pool node auth. + PoolPropertyPoolCA = C.DAOS_PROP_PO_POOL_CA + // PoolPropertyCertWatermarks is an opaque JSON blob of per-CN cert revocation watermarks. + PoolPropertyCertWatermarks = C.DAOS_PROP_PO_CERT_WATERMARKS ) const ( diff --git a/src/control/security/auth/auth.pb.go b/src/control/security/auth/auth.pb.go index a29840f2640..5140025b93b 100644 --- a/src/control/security/auth/auth.pb.go +++ b/src/control/security/auth/auth.pb.go @@ -1,5 +1,6 @@ // // (C) Copyright 2018-2021 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -7,7 +8,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.1 -// protoc v3.5.0 +// protoc v3.14.0 // source: auth.proto package auth @@ -280,21 +281,77 @@ func (x *Credential) GetOrigin() string { return "" } -// GetCredResp represents the result of a request to fetch authentication -// credentials. +type GetCredReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PoolId string `protobuf:"bytes,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + HandleUuid []byte `protobuf:"bytes,2,opt,name=handle_uuid,json=handleUuid,proto3" json:"handle_uuid,omitempty"` +} + +func (x *GetCredReq) Reset() { + *x = GetCredReq{} + if protoimpl.UnsafeEnabled { + mi := &file_auth_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetCredReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCredReq) ProtoMessage() {} + +func (x *GetCredReq) ProtoReflect() protoreflect.Message { + mi := &file_auth_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetCredReq.ProtoReflect.Descriptor instead. +func (*GetCredReq) Descriptor() ([]byte, []int) { + return file_auth_proto_rawDescGZIP(), []int{3} +} + +func (x *GetCredReq) GetPoolId() string { + if x != nil { + return x.PoolId + } + return "" +} + +func (x *GetCredReq) GetHandleUuid() []byte { + if x != nil { + return x.HandleUuid + } + return nil +} + type GetCredResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` // Status of the request - Cred *Credential `protobuf:"bytes,2,opt,name=cred,proto3" json:"cred,omitempty"` // Caller's authentication credential + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + Cred *Credential `protobuf:"bytes,2,opt,name=cred,proto3" json:"cred,omitempty"` + NodeCert []byte `protobuf:"bytes,3,opt,name=node_cert,json=nodeCert,proto3" json:"node_cert,omitempty"` + NodeCertPop []byte `protobuf:"bytes,4,opt,name=node_cert_pop,json=nodeCertPop,proto3" json:"node_cert_pop,omitempty"` + NodeCertPayload []byte `protobuf:"bytes,5,opt,name=node_cert_payload,json=nodeCertPayload,proto3" json:"node_cert_payload,omitempty"` } func (x *GetCredResp) Reset() { *x = GetCredResp{} if protoimpl.UnsafeEnabled { - mi := &file_auth_proto_msgTypes[3] + mi := &file_auth_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -307,7 +364,7 @@ func (x *GetCredResp) String() string { func (*GetCredResp) ProtoMessage() {} func (x *GetCredResp) ProtoReflect() protoreflect.Message { - mi := &file_auth_proto_msgTypes[3] + mi := &file_auth_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -320,7 +377,7 @@ func (x *GetCredResp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCredResp.ProtoReflect.Descriptor instead. func (*GetCredResp) Descriptor() ([]byte, []int) { - return file_auth_proto_rawDescGZIP(), []int{3} + return file_auth_proto_rawDescGZIP(), []int{4} } func (x *GetCredResp) GetStatus() int32 { @@ -337,6 +394,27 @@ func (x *GetCredResp) GetCred() *Credential { return nil } +func (x *GetCredResp) GetNodeCert() []byte { + if x != nil { + return x.NodeCert + } + return nil +} + +func (x *GetCredResp) GetNodeCertPop() []byte { + if x != nil { + return x.NodeCertPop + } + return nil +} + +func (x *GetCredResp) GetNodeCertPayload() []byte { + if x != nil { + return x.NodeCertPayload + } + return nil +} + // ValidateCredReq represents a request to verify a set of authentication // credentials. type ValidateCredReq struct { @@ -350,7 +428,7 @@ type ValidateCredReq struct { func (x *ValidateCredReq) Reset() { *x = ValidateCredReq{} if protoimpl.UnsafeEnabled { - mi := &file_auth_proto_msgTypes[4] + mi := &file_auth_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -363,7 +441,7 @@ func (x *ValidateCredReq) String() string { func (*ValidateCredReq) ProtoMessage() {} func (x *ValidateCredReq) ProtoReflect() protoreflect.Message { - mi := &file_auth_proto_msgTypes[4] + mi := &file_auth_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -376,7 +454,7 @@ func (x *ValidateCredReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateCredReq.ProtoReflect.Descriptor instead. func (*ValidateCredReq) Descriptor() ([]byte, []int) { - return file_auth_proto_rawDescGZIP(), []int{4} + return file_auth_proto_rawDescGZIP(), []int{5} } func (x *ValidateCredReq) GetCred() *Credential { @@ -400,7 +478,7 @@ type ValidateCredResp struct { func (x *ValidateCredResp) Reset() { *x = ValidateCredResp{} if protoimpl.UnsafeEnabled { - mi := &file_auth_proto_msgTypes[5] + mi := &file_auth_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -413,7 +491,7 @@ func (x *ValidateCredResp) String() string { func (*ValidateCredResp) ProtoMessage() {} func (x *ValidateCredResp) ProtoReflect() protoreflect.Message { - mi := &file_auth_proto_msgTypes[5] + mi := &file_auth_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -426,7 +504,7 @@ func (x *ValidateCredResp) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateCredResp.ProtoReflect.Descriptor instead. func (*ValidateCredResp) Descriptor() ([]byte, []int) { - return file_auth_proto_rawDescGZIP(), []int{5} + return file_auth_proto_rawDescGZIP(), []int{6} } func (x *ValidateCredResp) GetStatus() int32 { @@ -443,6 +521,156 @@ func (x *ValidateCredResp) GetToken() *Token { return nil } +type ValidateNodeCertReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PoolCa []byte `protobuf:"bytes,1,opt,name=pool_ca,json=poolCa,proto3" json:"pool_ca,omitempty"` + NodeCert []byte `protobuf:"bytes,2,opt,name=node_cert,json=nodeCert,proto3" json:"node_cert,omitempty"` + NodeCertPop []byte `protobuf:"bytes,3,opt,name=node_cert_pop,json=nodeCertPop,proto3" json:"node_cert_pop,omitempty"` + NodeCertPayload []byte `protobuf:"bytes,4,opt,name=node_cert_payload,json=nodeCertPayload,proto3" json:"node_cert_payload,omitempty"` + PoolId string `protobuf:"bytes,5,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + MachineName string `protobuf:"bytes,6,opt,name=machine_name,json=machineName,proto3" json:"machine_name,omitempty"` + CertWatermarks []byte `protobuf:"bytes,7,opt,name=cert_watermarks,json=certWatermarks,proto3" json:"cert_watermarks,omitempty"` +} + +func (x *ValidateNodeCertReq) Reset() { + *x = ValidateNodeCertReq{} + if protoimpl.UnsafeEnabled { + mi := &file_auth_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ValidateNodeCertReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateNodeCertReq) ProtoMessage() {} + +func (x *ValidateNodeCertReq) ProtoReflect() protoreflect.Message { + mi := &file_auth_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateNodeCertReq.ProtoReflect.Descriptor instead. +func (*ValidateNodeCertReq) Descriptor() ([]byte, []int) { + return file_auth_proto_rawDescGZIP(), []int{7} +} + +func (x *ValidateNodeCertReq) GetPoolCa() []byte { + if x != nil { + return x.PoolCa + } + return nil +} + +func (x *ValidateNodeCertReq) GetNodeCert() []byte { + if x != nil { + return x.NodeCert + } + return nil +} + +func (x *ValidateNodeCertReq) GetNodeCertPop() []byte { + if x != nil { + return x.NodeCertPop + } + return nil +} + +func (x *ValidateNodeCertReq) GetNodeCertPayload() []byte { + if x != nil { + return x.NodeCertPayload + } + return nil +} + +func (x *ValidateNodeCertReq) GetPoolId() string { + if x != nil { + return x.PoolId + } + return "" +} + +func (x *ValidateNodeCertReq) GetMachineName() string { + if x != nil { + return x.MachineName + } + return "" +} + +func (x *ValidateNodeCertReq) GetCertWatermarks() []byte { + if x != nil { + return x.CertWatermarks + } + return nil +} + +type ValidateNodeCertResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"` + Detail string `protobuf:"bytes,2,opt,name=detail,proto3" json:"detail,omitempty"` +} + +func (x *ValidateNodeCertResp) Reset() { + *x = ValidateNodeCertResp{} + if protoimpl.UnsafeEnabled { + mi := &file_auth_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ValidateNodeCertResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateNodeCertResp) ProtoMessage() {} + +func (x *ValidateNodeCertResp) ProtoReflect() protoreflect.Message { + mi := &file_auth_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateNodeCertResp.ProtoReflect.Descriptor instead. +func (*ValidateNodeCertResp) Descriptor() ([]byte, []int) { + return file_auth_proto_rawDescGZIP(), []int{8} +} + +func (x *ValidateNodeCertResp) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *ValidateNodeCertResp) GetDetail() string { + if x != nil { + return x.Detail + } + return "" +} + var File_auth_proto protoreflect.FileDescriptor var file_auth_proto_rawDesc = []byte{ @@ -468,27 +696,59 @@ var file_auth_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x22, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x72, 0x65, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x43, 0x72, - 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x63, 0x72, 0x65, 0x64, 0x22, 0x37, - 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, - 0x71, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x6e, 0x22, 0x46, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x12, + 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x55, 0x75, 0x69, 0x64, 0x22, 0xb8, 0x01, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x52, 0x04, 0x63, 0x72, 0x65, 0x64, 0x22, 0x4d, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, - 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2a, 0x25, 0x0a, 0x06, 0x46, 0x6c, 0x61, 0x76, 0x6f, 0x72, - 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, - 0x0c, 0x0a, 0x08, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x01, 0x42, 0x3b, 0x5a, - 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x61, 0x6f, 0x73, - 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2f, 0x73, 0x72, 0x63, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x2f, 0x61, 0x75, 0x74, 0x68, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6c, 0x52, 0x04, 0x63, 0x72, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x63, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x5f, 0x70, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6e, 0x6f, 0x64, + 0x65, 0x43, 0x65, 0x72, 0x74, 0x50, 0x6f, 0x70, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x6f, 0x64, 0x65, + 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x65, 0x72, 0x74, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x37, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x12, 0x24, 0x0a, 0x04, 0x63, 0x72, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x43, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x63, 0x72, 0x65, 0x64, 0x22, 0x4d, 0x0a, + 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x80, 0x02, 0x0a, + 0x13, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x52, 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x12, 0x1b, 0x0a, + 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x70, 0x6f, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x65, 0x72, 0x74, 0x50, 0x6f, 0x70, 0x12, 0x2a, + 0x0a, 0x11, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x43, + 0x65, 0x72, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, + 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, + 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x77, + 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0e, 0x63, 0x65, 0x72, 0x74, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x22, + 0x46, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x43, + 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x2a, 0x25, 0x0a, 0x06, 0x46, 0x6c, 0x61, 0x76, 0x6f, + 0x72, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, + 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x01, 0x42, 0x3b, + 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x61, 0x6f, + 0x73, 0x2d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x64, 0x61, 0x6f, 0x73, 0x2f, 0x73, 0x72, 0x63, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -504,15 +764,18 @@ func file_auth_proto_rawDescGZIP() []byte { } var file_auth_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_auth_proto_goTypes = []interface{}{ - (Flavor)(0), // 0: auth.Flavor - (*Token)(nil), // 1: auth.Token - (*Sys)(nil), // 2: auth.Sys - (*Credential)(nil), // 3: auth.Credential - (*GetCredResp)(nil), // 4: auth.GetCredResp - (*ValidateCredReq)(nil), // 5: auth.ValidateCredReq - (*ValidateCredResp)(nil), // 6: auth.ValidateCredResp + (Flavor)(0), // 0: auth.Flavor + (*Token)(nil), // 1: auth.Token + (*Sys)(nil), // 2: auth.Sys + (*Credential)(nil), // 3: auth.Credential + (*GetCredReq)(nil), // 4: auth.GetCredReq + (*GetCredResp)(nil), // 5: auth.GetCredResp + (*ValidateCredReq)(nil), // 6: auth.ValidateCredReq + (*ValidateCredResp)(nil), // 7: auth.ValidateCredResp + (*ValidateNodeCertReq)(nil), // 8: auth.ValidateNodeCertReq + (*ValidateNodeCertResp)(nil), // 9: auth.ValidateNodeCertResp } var file_auth_proto_depIdxs = []int32{ 0, // 0: auth.Token.flavor:type_name -> auth.Flavor @@ -571,7 +834,7 @@ func file_auth_proto_init() { } } file_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCredResp); i { + switch v := v.(*GetCredReq); i { case 0: return &v.state case 1: @@ -583,7 +846,7 @@ func file_auth_proto_init() { } } file_auth_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidateCredReq); i { + switch v := v.(*GetCredResp); i { case 0: return &v.state case 1: @@ -595,6 +858,18 @@ func file_auth_proto_init() { } } file_auth_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ValidateCredReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_auth_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateCredResp); i { case 0: return &v.state @@ -606,6 +881,30 @@ func file_auth_proto_init() { return nil } } + file_auth_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ValidateNodeCertReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_auth_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ValidateNodeCertResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -613,7 +912,7 @@ func file_auth_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_auth_proto_rawDesc, NumEnums: 1, - NumMessages: 6, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/src/control/security/config.go b/src/control/security/config.go index 7358e2e73ee..5d3f0d4a5fc 100644 --- a/src/control/security/config.go +++ b/src/control/security/config.go @@ -1,5 +1,6 @@ // // (C) Copyright 2019-2024 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -20,8 +21,10 @@ import ( ) const ( - certDir = "/etc/daos/certs/" - defaultCACert = certDir + "daosCA.crt" + certDir = "/etc/daos/certs/" + // DefaultCACertPath is the default path to the DAOS CA certificate. + DefaultCACertPath = certDir + "daosCA.crt" + defaultCACert = DefaultCACertPath defaultServerCert = certDir + "server.crt" defaultServerKey = certDir + "server.key" defaultAdminCert = certDir + "admin.crt" @@ -101,8 +104,9 @@ type CredentialConfig struct { // TransportConfig contains all the information on whether or not to use // certificates and their location if their use is specified. type TransportConfig struct { - AllowInsecure bool `yaml:"allow_insecure"` - CertificateConfig `yaml:",inline"` + AllowInsecure bool `yaml:"allow_insecure"` + PoolCertMaxClockSkew time.Duration `yaml:"pool_cert_max_clock_skew,omitempty"` + CertificateConfig `yaml:",inline"` } func (tc *TransportConfig) String() string { diff --git a/src/control/security/grpc_authorization.go b/src/control/security/grpc_authorization.go index d4fb9a2ad86..9e111a64ba6 100644 --- a/src/control/security/grpc_authorization.go +++ b/src/control/security/grpc_authorization.go @@ -64,6 +64,11 @@ var methodAuthorizations = map[string][]Component{ "/mgmt.MgmtSvc/PoolQueryTarget": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolSetProp": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolGetProp": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolGetCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolAddCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolRemoveCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolGetCertWatermarks": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolRevokeClient": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolGetACL": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolOverwriteACL": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolUpdateACL": {ComponentAdmin}, diff --git a/src/control/security/grpc_authorization_test.go b/src/control/security/grpc_authorization_test.go index 9eda8601cf5..a3da1d01701 100644 --- a/src/control/security/grpc_authorization_test.go +++ b/src/control/security/grpc_authorization_test.go @@ -81,6 +81,11 @@ func TestSecurity_ComponentHasAccess(t *testing.T) { "/mgmt.MgmtSvc/PoolQueryTarget": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolSetProp": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolGetProp": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolGetCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolAddCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolRemoveCA": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolGetCertWatermarks": {ComponentAdmin}, + "/mgmt.MgmtSvc/PoolRevokeClient": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolGetACL": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolOverwriteACL": {ComponentAdmin}, "/mgmt.MgmtSvc/PoolUpdateACL": {ComponentAdmin}, diff --git a/src/control/security/node_cert.go b/src/control/security/node_cert.go new file mode 100644 index 00000000000..73e3ee68de7 --- /dev/null +++ b/src/control/security/node_cert.go @@ -0,0 +1,118 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto" + "crypto/x509" + "encoding/pem" + "fmt" + "os" + "path/filepath" + "sync" + "time" + + "github.com/google/uuid" + "github.com/pkg/errors" + + "github.com/daos-stack/daos/src/control/logging" +) + +// NotBeforeSkewTolerance covers clock drift between admin (cert +// issuer) and agent. Also used as the server-side PoP timestamp skew. +const NotBeforeSkewTolerance = 5 * time.Minute + +// NodeCert is a loaded per-pool node certificate and key. +type NodeCert struct { + PEM []byte + Cert *x509.Certificate + Key crypto.PrivateKey +} + +// NodeCertLoader loads per-pool node certs from disk; refreshes on +// mtime/size change so revoked-and-reissued certs land without a restart. +type NodeCertLoader struct { + dir string + cache sync.Map +} + +// NewNodeCertLoader returns a loader that reads .{crt,key} from dir. +func NewNodeCertLoader(dir string) *NodeCertLoader { + return &NodeCertLoader{dir: dir} +} + +type fileSig struct { + mtime time.Time + size int64 +} + +type cachedNodeCert struct { + cert *NodeCert + certSig fileSig + keySig fileSig +} + +func statSig(path string) (fileSig, error) { + fi, err := os.Stat(path) + if err != nil { + return fileSig{}, err + } + return fileSig{mtime: fi.ModTime(), size: fi.Size()}, nil +} + +// Load returns poolID's cached cert+key, refreshing if either file has changed. +func (l *NodeCertLoader) Load(log logging.Logger, poolID string) (*NodeCert, error) { + poolUUID, err := uuid.Parse(poolID) + if err != nil { + return nil, errors.Wrap(err, "parsing pool UUID") + } + + certPath := filepath.Join(l.dir, poolUUID.String()+".crt") + keyPath := filepath.Join(l.dir, poolUUID.String()+".key") + + certSig, err := statSig(certPath) + if err != nil { + return nil, errors.Wrap(err, "stat node certificate") + } + keySig, err := statSig(keyPath) + if err != nil { + return nil, errors.Wrap(err, "stat node private key") + } + + if v, ok := l.cache.Load(poolID); ok { + c := v.(*cachedNodeCert) + if c.certSig == certSig && c.keySig == keySig { + return c.cert, nil + } + log.Debugf("node cert file for pool %s changed on disk; reloading", poolID) + } + + certPEM, err := LoadPEMData(certPath, MaxCertPerm) + if err != nil { + return nil, errors.Wrap(err, "loading node certificate") + } + block, _ := pem.Decode(certPEM) + if block == nil { + return nil, fmt.Errorf("invalid PEM data in %s", certPath) + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, errors.Wrap(err, "parsing node certificate") + } + key, err := LoadPrivateKey(keyPath) + if err != nil { + return nil, errors.Wrap(err, "loading node private key") + } + + nc := &NodeCert{PEM: certPEM, Cert: cert, Key: key} + l.cache.Store(poolID, &cachedNodeCert{cert: nc, certSig: certSig, keySig: keySig}) + + log.Debugf("loaded node cert for pool %s: CN=%s, expires=%s", + poolID, cert.Subject.CommonName, cert.NotAfter.Format(time.RFC3339)) + + return nc, nil +} diff --git a/src/control/security/node_cert_test.go b/src/control/security/node_cert_test.go new file mode 100644 index 00000000000..617946ed13e --- /dev/null +++ b/src/control/security/node_cert_test.go @@ -0,0 +1,131 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "os" + "path/filepath" + "testing" + "time" + + "github.com/daos-stack/daos/src/control/common/test" + "github.com/daos-stack/daos/src/control/logging" +) + +func writeTestNodeCert(t *testing.T, dir, poolUUID string) { + t.Helper() + + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + template := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: CertCNPrefixNode + "testhost"}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + } + certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) + if err != nil { + t.Fatal(err) + } + + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) + if err := os.WriteFile(filepath.Join(dir, poolUUID+".crt"), certPEM, 0644); err != nil { + t.Fatal(err) + } + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + t.Fatal(err) + } + keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}) + if err := os.WriteFile(filepath.Join(dir, poolUUID+".key"), keyPEM, 0400); err != nil { + t.Fatal(err) + } +} + +func TestNodeCertLoader_Load(t *testing.T) { + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + log, _ := logging.NewTestLogger(t.Name()) + loader := NewNodeCertLoader(tmpDir) + + poolUUID := "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" + writeTestNodeCert(t, tmpDir, poolUUID) + + c1, err := loader.Load(log, poolUUID) + if err != nil { + t.Fatalf("first load: %v", err) + } + c2, err := loader.Load(log, poolUUID) + if err != nil { + t.Fatalf("second load: %v", err) + } + if c1 != c2 { + t.Error("expected cache hit to return same pointer") + } + + // Missing cert -> error + if _, err := loader.Load(log, "bbbbbbbb-cccc-dddd-eeee-ffffffffffff"); err == nil { + t.Error("expected error for missing cert") + } + // Invalid pool UUID -> error + if _, err := loader.Load(log, "not-a-uuid"); err == nil { + t.Error("expected error for invalid pool UUID") + } +} + +func TestNodeCertLoader_ReloadOnFileChange(t *testing.T) { + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + log, _ := logging.NewTestLogger(t.Name()) + loader := NewNodeCertLoader(tmpDir) + + poolUUID := "cccccccc-dddd-eeee-ffff-000000000000" + writeTestNodeCert(t, tmpDir, poolUUID) + + c1, err := loader.Load(log, poolUUID) + if err != nil { + t.Fatalf("first load: %v", err) + } + + for _, name := range []string{poolUUID + ".crt", poolUUID + ".key"} { + if err := os.Remove(filepath.Join(tmpDir, name)); err != nil { + t.Fatalf("remove %s: %v", name, err) + } + } + writeTestNodeCert(t, tmpDir, poolUUID) + // Bump mtime past 1s resolution so a stat-based change detector + // reliably sees it regardless of filesystem granularity. + futureTime := time.Now().Add(2 * time.Second) + for _, name := range []string{poolUUID + ".crt", poolUUID + ".key"} { + p := filepath.Join(tmpDir, name) + if err := os.Chtimes(p, futureTime, futureTime); err != nil { + t.Fatalf("chtimes %s: %v", p, err) + } + } + + c2, err := loader.Load(log, poolUUID) + if err != nil { + t.Fatalf("reload: %v", err) + } + if c1 == c2 { + t.Error("expected cache to invalidate after cert file changed") + } +} diff --git a/src/control/security/pem.go b/src/control/security/pem.go index 707c771c592..bc197db000f 100644 --- a/src/control/security/pem.go +++ b/src/control/security/pem.go @@ -1,5 +1,6 @@ // // (C) Copyright 2019-2024 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -8,6 +9,7 @@ package security import ( "crypto" + "crypto/ecdsa" "crypto/rsa" "crypto/tls" "crypto/x509" @@ -24,8 +26,60 @@ const ( MaxGroupKeyPerm os.FileMode = 0440 MaxCertPerm os.FileMode = 0664 MaxDirPerm os.FileMode = 0750 + + // CertCNPrefixNode marks a node-scoped pool cert; suffix must match + // the local machine name. + CertCNPrefixNode = "node:" + // CertCNPrefixTenant marks a tenant-scoped pool cert shared across nodes. + CertCNPrefixTenant = "tenant:" + // CertCNSuffixMaxLen caps the portion of a pool cert CN after the + // prefix, matching the RFC 1035 maximum DNS name length. + CertCNSuffixMaxLen = 253 ) +// ValidatePoolCertCN parses a pool cert CN ("node:" or +// "tenant:"). Suffix is restricted to DNS-compatible chars to +// stop hostile values reaching cert-gen or watermark paths. +func ValidatePoolCertCN(cn string) (prefix, suffix string, err error) { + switch { + case strings.HasPrefix(cn, CertCNPrefixNode): + prefix = CertCNPrefixNode + case strings.HasPrefix(cn, CertCNPrefixTenant): + prefix = CertCNPrefixTenant + default: + return "", "", fmt.Errorf("CN %q must start with %q or %q", + cn, CertCNPrefixNode, CertCNPrefixTenant) + } + suffix = cn[len(prefix):] + if suffix == "" { + return "", "", fmt.Errorf("CN %q has empty suffix", cn) + } + if len(suffix) > CertCNSuffixMaxLen { + return "", "", fmt.Errorf("CN suffix %q exceeds max length %d", + suffix, CertCNSuffixMaxLen) + } + isAlnum := func(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') + } + if !isAlnum(suffix[0]) || !isAlnum(suffix[len(suffix)-1]) { + return "", "", fmt.Errorf("CN suffix %q must start and end with an alphanumeric", suffix) + } + for i := 0; i < len(suffix); i++ { + c := suffix[i] + switch { + case isAlnum(c): + case c == '.' || c == '-' || c == '_': + if i > 0 && !isAlnum(suffix[i-1]) { + return "", "", fmt.Errorf("CN suffix %q has consecutive separators", suffix) + } + default: + return "", "", fmt.Errorf("CN suffix %q contains disallowed character %q", + suffix, c) + } + } + return prefix, suffix, nil +} + type badPermsError struct { filename string perms os.FileMode @@ -193,9 +247,10 @@ func LoadPrivateKey(keyPath string) (crypto.PrivateKey, error) { key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err == nil { switch key := key.(type) { - // TODO: Support key types other than RSA case *rsa.PrivateKey: return key, nil + case *ecdsa.PrivateKey: + return key, nil default: return nil, fmt.Errorf("%s contains an unsupported private key type", keyPath) diff --git a/src/control/security/pem_test.go b/src/control/security/pem_test.go index 54990c37f47..3f27a7354f5 100644 --- a/src/control/security/pem_test.go +++ b/src/control/security/pem_test.go @@ -1,5 +1,6 @@ // // (C) Copyright 2019-2024 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -207,3 +208,53 @@ func TestSecurity_Pem_ValidateCertDirectory(t *testing.T) { }) } } + +func TestSecurity_ValidatePoolCertCN(t *testing.T) { + for name, tc := range map[string]struct { + cn string + wantPrefix string + wantSuffix string + wantErr string + }{ + "node ok": {cn: "node:host1", wantPrefix: "node:", wantSuffix: "host1"}, + "tenant ok": {cn: "tenant:teamA", wantPrefix: "tenant:", wantSuffix: "teamA"}, + "fqdn ok": {cn: "node:host1.example.com", wantPrefix: "node:", wantSuffix: "host1.example.com"}, + "underscore ok": {cn: "tenant:team_A", wantPrefix: "tenant:", wantSuffix: "team_A"}, + "no prefix": {cn: "host1", wantErr: "must start with"}, + "empty suffix node": {cn: "node:", wantErr: "empty suffix"}, + "empty suffix tenant": {cn: "tenant:", wantErr: "empty suffix"}, + "embedded null byte": {cn: "node:host\x00evil", wantErr: "disallowed character"}, + "embedded newline": {cn: "node:host\nhostile", wantErr: "disallowed character"}, + "embedded colon": {cn: "node:admin:bypass", wantErr: "disallowed character"}, + "space rejected": {cn: "node:host one", wantErr: "disallowed character"}, + "leading dot": {cn: "node:.host", wantErr: "must start and end with an alphanumeric"}, + "trailing dot": {cn: "node:host.", wantErr: "must start and end with an alphanumeric"}, + "leading hyphen": {cn: "node:-host", wantErr: "must start and end with an alphanumeric"}, + "consecutive dots": {cn: "node:host..example", wantErr: "consecutive separators"}, + "consecutive hyphens": {cn: "node:host--example", wantErr: "consecutive separators"}, + "too long": { + cn: "node:" + strings.Repeat("a", CertCNSuffixMaxLen+1), + wantErr: "exceeds max length", + }, + } { + t.Run(name, func(t *testing.T) { + prefix, suffix, err := ValidatePoolCertCN(tc.cn) + if tc.wantErr != "" { + if err == nil { + t.Fatalf("expected error containing %q, got nil", tc.wantErr) + } + if !strings.Contains(err.Error(), tc.wantErr) { + t.Fatalf("expected error containing %q, got %q", tc.wantErr, err.Error()) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if prefix != tc.wantPrefix || suffix != tc.wantSuffix { + t.Fatalf("got (%q, %q), want (%q, %q)", + prefix, suffix, tc.wantPrefix, tc.wantSuffix) + } + }) + } +} diff --git a/src/control/security/pool_cert.go b/src/control/security/pool_cert.go new file mode 100644 index 00000000000..6ea340116d7 --- /dev/null +++ b/src/control/security/pool_cert.go @@ -0,0 +1,237 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto/sha256" + "crypto/x509" + "encoding/json" + "encoding/pem" + "fmt" + "time" + + "github.com/pkg/errors" +) + +// CertWatermarks maps a pool cert CN to a NotBefore boundary. Certs whose +// NotBefore <= watermark are considered revoked; reissue must produce a +// cert with NotBefore strictly past the watermark. +type CertWatermarks map[string]time.Time + +// CertWatermarkRetention bounds the watermark history. An entry older than +// retention can be pruned because any cert covered by it has long since +// passed its NotAfter and would be rejected by the standard validity check. +// Admins issuing certs with validity greater than this must bump it. +const CertWatermarkRetention = 5 * 365 * 24 * time.Hour + +// PruneCertWatermarks returns wm minus entries with watermark before cutoff, +// along with the number of entries dropped. +func PruneCertWatermarks(wm CertWatermarks, cutoff time.Time) (CertWatermarks, int) { + if len(wm) == 0 { + return wm, 0 + } + out := make(CertWatermarks, len(wm)) + pruned := 0 + for cn, t := range wm { + if t.Before(cutoff) { + pruned++ + continue + } + out[cn] = t + } + return out, pruned +} + +// EncodeCertWatermarks serializes wm as JSON. An empty map encodes to nil +// so the prop layer can distinguish "no revocations" from an empty blob. +func EncodeCertWatermarks(wm CertWatermarks) ([]byte, error) { + if len(wm) == 0 { + return nil, nil + } + raw := make(map[string]string, len(wm)) + for cn, t := range wm { + raw[cn] = t.UTC().Format(time.RFC3339) + } + return json.Marshal(raw) +} + +// DecodeCertWatermarks parses the JSON watermarks blob. +func DecodeCertWatermarks(data []byte) (CertWatermarks, error) { + raw := make(map[string]string) + if err := json.Unmarshal(data, &raw); err != nil { + return nil, errors.Wrap(err, "parsing cert watermarks blob") + } + out := make(CertWatermarks, len(raw)) + for cn, ts := range raw { + t, err := time.Parse(time.RFC3339, ts) + if err != nil { + return nil, errors.Wrapf(err, "parsing watermark for %s", cn) + } + out[cn] = t.UTC() + } + return out, nil +} + +// AdvanceCertWatermark returns a value strictly greater than the existing +// watermark for cn. Monotonicity is mandatory: lowering a watermark would +// silently re-validate an already-revoked cert. +func AdvanceCertWatermark(existing CertWatermarks, cn string, now time.Time) time.Time { + now = now.UTC().Truncate(time.Second) + if prev, ok := existing[cn]; ok && !now.After(prev) { + return prev.Add(time.Second) + } + return now +} + +// RemoveCertByFingerprint drops PEM certs matching a SHA-256 hex fingerprint. +func RemoveCertByFingerprint(bundle []byte, fingerprint string) ([]byte, int, error) { + var remaining []byte + removed := 0 + rest := bundle + + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, 0, fmt.Errorf("unexpected PEM block type %q in CA bundle", block.Type) + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, 0, errors.Wrap(err, "malformed cert in CA bundle") + } + fp := fmt.Sprintf("%x", sha256.Sum256(cert.Raw)) + if fp == fingerprint { + removed++ + continue + } + remaining = append(remaining, pem.EncodeToMemory(block)...) + } + + if removed == 0 { + return nil, 0, fmt.Errorf("no CA with fingerprint %s found in bundle", fingerprint) + } + + return remaining, removed, nil +} + +// CountPEMCerts returns the number of CERTIFICATE blocks in a PEM bundle. +func CountPEMCerts(bundle []byte) int { + count := 0 + rest := bundle + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type == "CERTIFICATE" { + count++ + } + } + return count +} + +// ParsePoolCACert parses a single-block CA cert and enforces IsCA + KeyCertSign. +func ParsePoolCACert(certPEM []byte) (*x509.Certificate, error) { + block, rest := pem.Decode(certPEM) + if block == nil || block.Type != "CERTIFICATE" { + return nil, errors.New("cert_pem is not a PEM-encoded CERTIFICATE block") + } + if len(rest) > 0 { + trailing, _ := pem.Decode(rest) + if trailing != nil { + return nil, errors.New("cert_pem must contain exactly one CERTIFICATE block") + } + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, errors.Wrap(err, "parsing CA certificate") + } + if !cert.IsCA { + return nil, errors.New("certificate does not have IsCA=true") + } + if cert.KeyUsage&x509.KeyUsageCertSign == 0 { + return nil, errors.New("certificate KeyUsage does not include KeyCertSign") + } + return cert, nil +} + +// VerifyPoolCAChain confirms cert chains to the DAOS root at rootCAPath. +// Empty rootCAPath skips verification (AllowInsecure mode). +func VerifyPoolCAChain(cert *x509.Certificate, rootCAPath string) error { + if rootCAPath == "" { + return nil + } + root, err := LoadCertificate(rootCAPath) + if err != nil { + return errors.Wrap(err, "loading DAOS CA certificate") + } + pool := x509.NewCertPool() + pool.AddCert(root) + + // ExtKeyUsageAny: the DAOS CA is not EKU-constrained; care only about chain validity. + _, err = cert.Verify(x509.VerifyOptions{ + Roots: pool, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, + }) + if err != nil { + return errors.Wrap(err, "pool CA does not chain to DAOS CA") + } + return nil +} + +// AppendCACert validates certPEM as a pool CA and appends it to the bundle. +func AppendCACert(existing, certPEM []byte) ([]byte, error) { + if _, err := ParsePoolCACert(certPEM); err != nil { + return nil, err + } + combined := make([]byte, 0, len(existing)+len(certPEM)) + combined = append(combined, existing...) + combined = append(combined, certPEM...) + return combined, nil +} + +// PoolCertInfo summarizes a single PEM CA certificate. +type PoolCertInfo struct { + Subject string `json:"subject"` + Issuer string `json:"issuer"` + NotBefore string `json:"not_before"` + NotAfter string `json:"not_after"` + Fingerprint string `json:"fingerprint"` +} + +// ParseCABundle decodes a PEM bundle into a slice of PoolCertInfo entries. +func ParseCABundle(bundle []byte) ([]PoolCertInfo, error) { + var out []PoolCertInfo + rest := bundle + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf("unexpected PEM block type %q in CA bundle", block.Type) + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, errors.Wrap(err, "malformed cert in CA bundle") + } + fp := sha256.Sum256(cert.Raw) + out = append(out, PoolCertInfo{ + Subject: cert.Subject.String(), + Issuer: cert.Issuer.String(), + NotBefore: cert.NotBefore.Format(time.RFC3339), + NotAfter: cert.NotAfter.Format(time.RFC3339), + Fingerprint: fmt.Sprintf("%x", fp), + }) + } + return out, nil +} diff --git a/src/control/security/pool_cert_test.go b/src/control/security/pool_cert_test.go new file mode 100644 index 00000000000..020d34dcedc --- /dev/null +++ b/src/control/security/pool_cert_test.go @@ -0,0 +1,358 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func TestDecodeCertWatermarks(t *testing.T) { + for name, tc := range map[string]struct { + input string + wantLen int + wantErr bool + }{ + "empty object": {`{}`, 0, false}, + "one entry": {`{"node:host1":"2026-01-02T03:04:05Z"}`, 1, false}, + "two entries": {`{"node:host1":"2026-01-02T03:04:05Z","tenant:t1":"2026-02-01T00:00:00Z"}`, 2, false}, + "malformed JSON": {`not json`, 0, true}, + "bad timestamp": {`{"node:host1":"not-a-time"}`, 0, true}, + "missing timezone": {`{"node:host1":"2026-01-02T03:04:05"}`, 0, true}, + } { + t.Run(name, func(t *testing.T) { + got, err := DecodeCertWatermarks([]byte(tc.input)) + if tc.wantErr { + if err == nil { + t.Fatal("expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(got) != tc.wantLen { + t.Errorf("got %d entries, want %d", len(got), tc.wantLen) + } + for cn, ts := range got { + if ts.Location() != time.UTC { + t.Errorf("watermark for %q is not UTC: %v", cn, ts) + } + } + }) + } +} + +func TestCertWatermarks_RoundTrip(t *testing.T) { + for name, tc := range map[string]struct { + input CertWatermarks + }{ + "empty": {input: nil}, + "single node": {input: CertWatermarks{ + "node:node1": time.Date(2026, 4, 15, 14, 0, 29, 0, time.UTC), + }}, + "multiple": {input: CertWatermarks{ + "node:node1": time.Date(2026, 4, 15, 14, 0, 29, 0, time.UTC), + "node:node2": time.Date(2026, 4, 15, 14, 0, 30, 0, time.UTC), + "tenant:teamA": time.Date(2026, 4, 20, 9, 15, 0, 0, time.UTC), + }}, + } { + t.Run(name, func(t *testing.T) { + encoded, err := EncodeCertWatermarks(tc.input) + if err != nil { + t.Fatalf("encode: %v", err) + } + if len(tc.input) == 0 { + if encoded != nil { + t.Fatalf("empty map must encode to nil, got %q", encoded) + } + return + } + got, err := DecodeCertWatermarks(encoded) + if err != nil { + t.Fatalf("decode: %v", err) + } + if diff := cmp.Diff(tc.input, got); diff != "" { + t.Fatalf("round-trip mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func TestAdvanceCertWatermark(t *testing.T) { + t0 := time.Date(2026, 4, 15, 14, 0, 0, 0, time.UTC) + for name, tc := range map[string]struct { + existing CertWatermarks + cn string + now time.Time + want time.Time + }{ + "no prior": {nil, "node:n1", t0.Add(500 * time.Millisecond), t0}, + "no prior for cn": {CertWatermarks{"node:other": t0.Add(time.Hour)}, "node:n1", t0, t0}, + "now > prior": {CertWatermarks{"node:n1": t0}, "node:n1", t0.Add(time.Minute), t0.Add(time.Minute)}, + "now == prior": {CertWatermarks{"node:n1": t0}, "node:n1", t0, t0.Add(time.Second)}, + "now < prior": {CertWatermarks{"node:n1": t0.Add(time.Hour)}, "node:n1", t0, t0.Add(time.Hour).Add(time.Second)}, + "sub-second truncated": {nil, "node:n1", t0.Add(999 * time.Millisecond), t0}, + } { + t.Run(name, func(t *testing.T) { + got := AdvanceCertWatermark(tc.existing, tc.cn, tc.now) + if !got.Equal(tc.want) { + t.Errorf("got %s, want %s", got.Format(time.RFC3339), tc.want.Format(time.RFC3339)) + } + }) + } +} + +func TestPruneCertWatermarks(t *testing.T) { + t0 := time.Date(2026, 4, 15, 14, 0, 0, 0, time.UTC) + wm := CertWatermarks{ + "node:fresh": t0, + "node:stale": t0.Add(-CertWatermarkRetention - time.Hour), + "node:boundary": t0.Add(-CertWatermarkRetention), // exactly at cutoff stays + } + out, pruned := PruneCertWatermarks(wm, t0.Add(-CertWatermarkRetention)) + if pruned != 1 { + t.Fatalf("pruned=%d, want 1", pruned) + } + if _, ok := out["node:stale"]; ok { + t.Errorf("stale entry survived prune") + } + if _, ok := out["node:fresh"]; !ok { + t.Errorf("fresh entry was pruned") + } + if _, ok := out["node:boundary"]; !ok { + t.Errorf("boundary entry (==cutoff) was pruned") + } +} + +// generateTestCA produces a self-signed CA cert + key. +func generateTestCA(t *testing.T, cn string) (*x509.Certificate, *ecdsa.PrivateKey, []byte) { + t.Helper() + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + IsCA: true, + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + BasicConstraintsValid: true, + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) + if err != nil { + t.Fatal(err) + } + cert, _ := x509.ParseCertificate(der) + pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}) + return cert, key, pemBytes +} + +// signCertWith creates a leaf cert (or intermediate CA) signed by parent. +func signCertWith(t *testing.T, parent *x509.Certificate, parentKey *ecdsa.PrivateKey, cn string, isCA bool) ([]byte, *x509.Certificate) { + t.Helper() + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + usage := x509.KeyUsageDigitalSignature + if isCA { + usage |= x509.KeyUsageCertSign + } + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + IsCA: isCA, + KeyUsage: usage, + BasicConstraintsValid: true, + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, parent, &key.PublicKey, parentKey) + if err != nil { + t.Fatal(err) + } + cert, _ := x509.ParseCertificate(der) + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), cert +} + +func TestRemoveCertByFingerprint(t *testing.T) { + _, _, pemA := generateTestCA(t, "CA-A") + certA, _ := x509.ParseCertificate(decodePEM(t, pemA)) + _, _, pemB := generateTestCA(t, "CA-B") + certB, _ := x509.ParseCertificate(decodePEM(t, pemB)) + _, _, pemC := generateTestCA(t, "CA-C") + + bundle := append(append(pemA, pemB...), pemC...) + fpA := fmt.Sprintf("%x", sha256.Sum256(certA.Raw)) + fpB := fmt.Sprintf("%x", sha256.Sum256(certB.Raw)) + + for name, tc := range map[string]struct { + fp string + want int + errSub string + }{ + "remove first": {fpA, 1, ""}, + "remove middle": {fpB, 1, ""}, + "not found": {"deadbeef", 0, "no CA with fingerprint"}, + } { + t.Run(name, func(t *testing.T) { + _, removed, err := RemoveCertByFingerprint(bundle, tc.fp) + if tc.errSub != "" { + if err == nil { + t.Fatal("expected error") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if removed != tc.want { + t.Errorf("removed=%d, want %d", removed, tc.want) + } + }) + } +} + +func TestRemoveCertByFingerprint_MalformedBundle(t *testing.T) { + _, _, validCA := generateTestCA(t, "valid") + + // Non-CERTIFICATE PEM block in bundle is rejected. + notACert := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("x")}) + if _, _, err := RemoveCertByFingerprint(append(validCA, notACert...), "anything"); err == nil { + t.Fatal("expected error for non-CERTIFICATE PEM block") + } + + // CERTIFICATE block with garbage bytes is rejected. + garbage := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte("not der")}) + if _, _, err := RemoveCertByFingerprint(append(validCA, garbage...), "anything"); err == nil { + t.Fatal("expected error for malformed CERTIFICATE block") + } +} + +func TestCountPEMCerts(t *testing.T) { + _, _, pemA := generateTestCA(t, "A") + _, _, pemB := generateTestCA(t, "B") + if got := CountPEMCerts(pemA); got != 1 { + t.Errorf("one cert: got %d, want 1", got) + } + if got := CountPEMCerts(append(pemA, pemB...)); got != 2 { + t.Errorf("two certs: got %d, want 2", got) + } + if got := CountPEMCerts(nil); got != 0 { + t.Errorf("nil bundle: got %d, want 0", got) + } + // A non-CERTIFICATE block does not count. + notACert := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("x")}) + if got := CountPEMCerts(append(pemA, notACert...)); got != 1 { + t.Errorf("cert+other: got %d, want 1", got) + } +} + +func TestParsePoolCACert(t *testing.T) { + _, _, caPEM := generateTestCA(t, "valid CA") + + // Build a non-CA cert (leaf) for the IsCA-false case. + rootCert, rootKey, _ := generateTestCA(t, "root") + leafPEM, _ := signCertWith(t, rootCert, rootKey, "leaf", false) + + for name, tc := range map[string]struct { + input []byte + wantErr string + }{ + "valid CA": {caPEM, ""}, + "not a CA": {leafPEM, "IsCA"}, + "empty input": {nil, "PEM-encoded CERTIFICATE"}, + "two blocks": {append(caPEM, caPEM...), "exactly one CERTIFICATE"}, + } { + t.Run(name, func(t *testing.T) { + _, err := ParsePoolCACert(tc.input) + if tc.wantErr != "" { + if err == nil { + t.Fatal("expected error") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + } +} + +func TestVerifyPoolCAChain(t *testing.T) { + rootCert, rootKey, rootPEM := generateTestCA(t, "root") + _, interPEM := signCertWith(t, rootCert, rootKey, "pool CA", true) + + // Write root to a temp file (LoadCertificate requires MaxCertPerm). + dir := t.TempDir() + rootPath := filepath.Join(dir, "root.crt") + if err := os.WriteFile(rootPath, rootPEM, MaxCertPerm); err != nil { + t.Fatal(err) + } + + if err := VerifyPoolCAChain(interPEM, rootPath); err != nil { + t.Fatalf("valid chain rejected: %v", err) + } + + // Empty rootCAPath skips verification (AllowInsecure mode). + if err := VerifyPoolCAChain(interPEM, ""); err != nil { + t.Fatalf("empty rootCAPath should be a no-op: %v", err) + } + + // Cert signed by a different root must not validate against rootPath. + freshRoot, freshKey, _ := generateTestCA(t, "fresh root") + _, badPEM := signCertWith(t, freshRoot, freshKey, "bad chain", true) + if err := VerifyPoolCAChain(badPEM, rootPath); err == nil { + t.Fatal("cert not chaining to root should be rejected") + } +} + +func TestAppendCACert(t *testing.T) { + _, _, caA := generateTestCA(t, "A") + _, _, caB := generateTestCA(t, "B") + bundle, err := AppendCACert(caA, caB) + if err != nil { + t.Fatalf("valid append failed: %v", err) + } + if CountPEMCerts(bundle) != 2 { + t.Errorf("bundle should have 2 certs, got %d", CountPEMCerts(bundle)) + } + // Non-CA cert rejected. + root, key, _ := generateTestCA(t, "root") + leaf, _ := signCertWith(t, root, key, "leaf", false) + if _, err := AppendCACert(caA, leaf); err == nil { + t.Fatal("AppendCACert should reject non-CA cert") + } +} + +// decodePEM returns the DER bytes of the first PEM block, or fails. +func decodePEM(t *testing.T, data []byte) []byte { + t.Helper() + block, _ := pem.Decode(data) + if block == nil { + t.Fatal("no PEM block") + } + return block.Bytes +} diff --git a/src/control/security/pop.go b/src/control/security/pop.go new file mode 100644 index 00000000000..6f31843d51f --- /dev/null +++ b/src/control/security/pop.go @@ -0,0 +1,97 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "encoding/binary" + "fmt" + "time" + + "github.com/google/uuid" +) + +const PoPPayloadLen = 40 + +// popSigDomain separates PoP signatures from any other signing operation +// that might reuse a node cert key. +const popSigDomain = "DAOS-NODE-POP-V1\x00" + +// BuildPoPPayload assembles a fresh proof-of-possession payload. +func BuildPoPPayload(poolUUID uuid.UUID, handleUUID []byte) []byte { + payload := make([]byte, PoPPayloadLen) + copy(payload[0:16], poolUUID[:]) + copy(payload[16:32], handleUUID) + binary.BigEndian.PutUint64(payload[32:40], uint64(time.Now().Unix())) + return payload +} + +// SignPoP signs payload with key, using a hash chosen for the key type. +func SignPoP(key crypto.PrivateKey, cert *x509.Certificate, payload []byte) ([]byte, error) { + signInput := append([]byte(popSigDomain), payload...) + switch k := key.(type) { + case *rsa.PrivateKey: + h := sha512.Sum512(signInput) + return rsa.SignPSS(rand.Reader, k, crypto.SHA512, h[:], &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: crypto.SHA512, + }) + case *ecdsa.PrivateKey: + var hash []byte + switch k.Curve { + case elliptic.P256(): + h := sha256.Sum256(signInput) + hash = h[:] + case elliptic.P384(): + h := sha512.Sum384(signInput) + hash = h[:] + default: + return nil, fmt.Errorf("unsupported ECDSA curve: %v", k.Curve.Params().Name) + } + return ecdsa.SignASN1(rand.Reader, k, hash) + default: + return nil, fmt.Errorf("unsupported key type: %T", key) + } +} + +// VerifyPoP verifies a SignPoP signature using the matching domain prefix. +func VerifyPoP(pub crypto.PublicKey, payload, sig []byte) error { + signInput := append([]byte(popSigDomain), payload...) + switch k := pub.(type) { + case *rsa.PublicKey: + h := sha512.Sum512(signInput) + return rsa.VerifyPSS(k, crypto.SHA512, h[:], sig, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: crypto.SHA512, + }) + case *ecdsa.PublicKey: + var hash []byte + switch k.Curve { + case elliptic.P256(): + h := sha256.Sum256(signInput) + hash = h[:] + case elliptic.P384(): + h := sha512.Sum384(signInput) + hash = h[:] + default: + return fmt.Errorf("unsupported ECDSA curve: %v", k.Curve.Params().Name) + } + if !ecdsa.VerifyASN1(k, hash, sig) { + return fmt.Errorf("ECDSA signature verification failed") + } + return nil + default: + return fmt.Errorf("unsupported public key type: %T", pub) + } +} diff --git a/src/control/security/pop_test.go b/src/control/security/pop_test.go new file mode 100644 index 00000000000..1e3d2ee7ef7 --- /dev/null +++ b/src/control/security/pop_test.go @@ -0,0 +1,165 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package security + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "encoding/binary" + "testing" + "time" + + "github.com/google/uuid" +) + +func TestBuildPoPPayload(t *testing.T) { + poolUUID := uuid.MustParse("12345678-1234-1234-1234-123456789abc") + handleUUID := uuid.MustParse("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee") + + before := time.Now().Unix() + payload := BuildPoPPayload(poolUUID, handleUUID[:]) + after := time.Now().Unix() + + if len(payload) != PoPPayloadLen { + t.Fatalf("expected %d bytes, got %d", PoPPayloadLen, len(payload)) + } + + var gotPoolUUID uuid.UUID + copy(gotPoolUUID[:], payload[0:16]) + if gotPoolUUID != poolUUID { + t.Errorf("pool UUID mismatch: got %s, want %s", gotPoolUUID, poolUUID) + } + + var gotHandleUUID uuid.UUID + copy(gotHandleUUID[:], payload[16:32]) + if gotHandleUUID != handleUUID { + t.Errorf("handle UUID mismatch: got %s, want %s", gotHandleUUID, handleUUID) + } + + ts := int64(binary.BigEndian.Uint64(payload[32:40])) + if ts < before || ts > after { + t.Errorf("timestamp %d not in range [%d, %d]", ts, before, after) + } +} + +func TestSignPoP_ECDSA_P384(t *testing.T) { + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{PublicKey: &key.PublicKey} + payload := make([]byte, PoPPayloadLen) + if _, err := rand.Read(payload); err != nil { + t.Fatal(err) + } + + sig, err := SignPoP(key, cert, payload) + if err != nil { + t.Fatalf("SignPoP failed: %v", err) + } + h := sha512.Sum384(append([]byte(popSigDomain), payload...)) + if !ecdsa.VerifyASN1(&key.PublicKey, h[:], sig) { + t.Fatal("ECDSA P-384 signature verification failed") + } +} + +func TestSignPoP_ECDSA_P256(t *testing.T) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{PublicKey: &key.PublicKey} + payload := make([]byte, PoPPayloadLen) + if _, err := rand.Read(payload); err != nil { + t.Fatal(err) + } + + sig, err := SignPoP(key, cert, payload) + if err != nil { + t.Fatalf("SignPoP failed: %v", err) + } + h := sha256.Sum256(append([]byte(popSigDomain), payload...)) + if !ecdsa.VerifyASN1(&key.PublicKey, h[:], sig) { + t.Fatal("ECDSA P-256 signature verification failed") + } +} + +func TestSignPoP_RSA(t *testing.T) { + key, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{PublicKey: &key.PublicKey} + payload := make([]byte, PoPPayloadLen) + if _, err := rand.Read(payload); err != nil { + t.Fatal(err) + } + + sig, err := SignPoP(key, cert, payload) + if err != nil { + t.Fatalf("SignPoP failed: %v", err) + } + h := sha512.Sum512(append([]byte(popSigDomain), payload...)) + if err := rsa.VerifyPSS(&key.PublicKey, crypto.SHA512, h[:], sig, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: crypto.SHA512, + }); err != nil { + t.Fatalf("RSA-PSS signature verification failed: %v", err) + } +} + +func TestVerifyPoP_RoundTrip(t *testing.T) { + payload := make([]byte, PoPPayloadLen) + if _, err := rand.Read(payload); err != nil { + t.Fatal(err) + } + + ec384, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + ec256, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + + for name, k := range map[string]struct { + priv crypto.PrivateKey + pub crypto.PublicKey + }{ + "ECDSA P-384": {ec384, &ec384.PublicKey}, + "ECDSA P-256": {ec256, &ec256.PublicKey}, + "RSA-PSS": {rsaKey, &rsaKey.PublicKey}, + } { + t.Run(name, func(t *testing.T) { + sig, err := SignPoP(k.priv, nil, payload) + if err != nil { + t.Fatalf("SignPoP: %v", err) + } + if err := VerifyPoP(k.pub, payload, sig); err != nil { + t.Fatalf("VerifyPoP: %v", err) + } + // Tampering the payload must fail verification. + tampered := make([]byte, len(payload)) + copy(tampered, payload) + tampered[0] ^= 0xff + if err := VerifyPoP(k.pub, tampered, sig); err == nil { + t.Fatal("VerifyPoP accepted a tampered payload") + } + }) + } +} diff --git a/src/control/security/test/testca.go b/src/control/security/test/testca.go new file mode 100644 index 00000000000..2fa5fd78197 --- /dev/null +++ b/src/control/security/test/testca.go @@ -0,0 +1,92 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +// Package test provides crypto fixtures for DAOS test code. +package test + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + "time" +) + +// NewCA returns a fresh CA cert (PEM) and its private key. If parent is +// non-nil the new cert is signed by parent/parentKey; otherwise it is +// self-signed. +func NewCA(t *testing.T, cn string, parent *x509.Certificate, parentKey *ecdsa.PrivateKey) ([]byte, *ecdsa.PrivateKey) { + t.Helper() + key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatal(err) + } + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + tmpl := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: cn}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageCertSign, + BasicConstraintsValid: true, + IsCA: true, + } + issuer := tmpl + signerKey := key + if parent != nil { + issuer = parent + signerKey = parentKey + } + der, err := x509.CreateCertificate(rand.Reader, tmpl, issuer, &key.PublicKey, signerKey) + if err != nil { + t.Fatal(err) + } + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), key +} + +// CertFingerprint returns the SHA-256 fingerprint (hex) of a PEM cert. +func CertFingerprint(t *testing.T, certPEM []byte) string { + t.Helper() + block, _ := pem.Decode(certPEM) + if block == nil { + t.Fatal("pem.Decode returned nil block") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatal(err) + } + return fmt.Sprintf("%x", sha256.Sum256(cert.Raw)) +} + +// WriteCAFiles writes a fresh self-signed CA cert + key into dir as +// "test_ca.crt" / "test_ca.key" and returns their paths. +func WriteCAFiles(t *testing.T, dir string) (keyPath, certPath string) { + t.Helper() + certPEM, key := NewCA(t, "Test CA", nil, nil) + certPath = filepath.Join(dir, "test_ca.crt") + if err := os.WriteFile(certPath, certPEM, 0644); err != nil { + t.Fatal(err) + } + keyDER, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + t.Fatal(err) + } + keyPath = filepath.Join(dir, "test_ca.key") + if err := os.WriteFile(keyPath, + pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), + 0400); err != nil { + t.Fatal(err) + } + return keyPath, certPath +} diff --git a/src/control/server/mgmt_pool.go b/src/control/server/mgmt_pool.go index dbe5f0d5ae9..fbe33875e7b 100644 --- a/src/control/server/mgmt_pool.go +++ b/src/control/server/mgmt_pool.go @@ -1,6 +1,6 @@ // // (C) Copyright 2020-2024 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -10,6 +10,7 @@ package server import ( "math/rand" "sort" + "strings" "time" "github.com/dustin/go-humanize" @@ -24,6 +25,7 @@ import ( "github.com/daos-stack/daos/src/control/fault/code" "github.com/daos-stack/daos/src/control/lib/daos" "github.com/daos-stack/daos/src/control/lib/ranklist" + "github.com/daos-stack/daos/src/control/security" "github.com/daos-stack/daos/src/control/server/engine" "github.com/daos-stack/daos/src/control/server/storage" "github.com/daos-stack/daos/src/control/system" @@ -1118,6 +1120,15 @@ func (svc *mgmtSvc) PoolSetProp(parent context.Context, req *mgmtpb.PoolSetPropR return nil, errors.New("PoolSetProp() request with 0 properties") } + for _, prop := range req.GetProperties() { + switch prop.GetNumber() { + case daos.PoolPropertyPoolCA: + return nil, errors.New("pool_ca must be set via PoolAddCA/PoolRemoveCA") + case daos.PoolPropertyCertWatermarks: + return nil, errors.New("cert_watermarks must be set via PoolRevokeClient") + } + } + miscProps := make([]*mgmtpb.PoolProperty, 0, len(req.GetProperties())) for _, prop := range req.GetProperties() { // Label is a special case, in that we need to ensure that it's unique @@ -1183,6 +1194,305 @@ func (svc *mgmtSvc) PoolGetProp(ctx context.Context, req *mgmtpb.PoolGetPropReq) return resp, nil } +// readPoolProperty reads a byteval pool property; returns nil if unset. +func (svc *mgmtSvc) readPoolProperty(ctx context.Context, sys, id string, propNum uint32) ([]byte, error) { + getReq := &mgmtpb.PoolGetPropReq{ + Sys: sys, + Id: id, + Properties: []*mgmtpb.PoolProperty{ + {Number: propNum}, + }, + } + dResp, err := svc.makePoolServiceCall(ctx, daos.MethodPoolGetProp, getReq) + if err != nil { + return nil, err + } + getResp := new(mgmtpb.PoolGetPropResp) + if err := svc.unmarshalPB(dResp.Body, getResp); err != nil { + return nil, err + } + if getResp.GetStatus() != 0 { + return nil, errors.Errorf("PoolGetProp returned status %d", getResp.GetStatus()) + } + for _, prop := range getResp.GetProperties() { + if prop.GetNumber() != propNum { + continue + } + return prop.GetByteval(), nil + } + return nil, nil +} + +// writePoolByteProperty writes a byteval pool property; invariants are the caller's job. +func (svc *mgmtSvc) writePoolByteProperty(ctx context.Context, sys, id string, propNum uint32, value []byte) error { + setReq := &mgmtpb.PoolSetPropReq{ + Sys: sys, + Id: id, + Properties: []*mgmtpb.PoolProperty{ + { + Number: propNum, + Value: &mgmtpb.PoolProperty_Byteval{Byteval: value}, + }, + }, + } + dResp, err := svc.makePoolServiceCall(ctx, daos.MethodPoolSetProp, setReq) + if err != nil { + return err + } + setResp := new(mgmtpb.PoolSetPropResp) + if err := svc.unmarshalPB(dResp.Body, setResp); err != nil { + return err + } + if setResp.GetStatus() != 0 { + ds := daos.Status(setResp.GetStatus()) + if ds == daos.NotSupported { + return errors.Errorf("pool must be upgraded; run `dmg pool upgrade %s` first", id) + } + return ds + } + return nil +} + +// poolCABundleMaxCerts bounds the bundle so per-connect parse cost stays +// predictable; sized to cover a primary plus crossover CAs during rotation. +const poolCABundleMaxCerts = 8 + +// PoolGetCA returns the pool's CA bundle. +func (svc *mgmtSvc) PoolGetCA(ctx context.Context, req *mgmtpb.PoolGetCAReq) (*mgmtpb.PoolGetCAResp, error) { + if err := svc.checkReplicaRequest(req); err != nil { + return nil, err + } + poolUUID, err := svc.resolvePoolID(req.GetId()) + if err != nil { + return nil, err + } + bundle, err := svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA) + if err != nil { + return nil, errors.Wrap(err, "reading pool CA bundle") + } + return &mgmtpb.PoolGetCAResp{CaBundle: bundle, PoolUuid: poolUUID.String()}, nil +} + +// PoolGetCertWatermarks returns the pool's per-CN revocation watermarks blob. +func (svc *mgmtSvc) PoolGetCertWatermarks(ctx context.Context, req *mgmtpb.PoolGetCertWatermarksReq) (*mgmtpb.PoolGetCertWatermarksResp, error) { + if err := svc.checkReplicaRequest(req); err != nil { + return nil, err + } + poolUUID, err := svc.resolvePoolID(req.GetId()) + if err != nil { + return nil, err + } + watermarks, err := svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyCertWatermarks) + if err != nil { + return nil, errors.Wrap(err, "reading cert watermarks") + } + return &mgmtpb.PoolGetCertWatermarksResp{Watermarks: watermarks, PoolUuid: poolUUID.String()}, nil +} + +// PoolAddCA appends a CA cert to the pool's CA bundle under the pool lock. +func (svc *mgmtSvc) PoolAddCA(parent context.Context, req *mgmtpb.PoolAddCAReq) (*mgmtpb.PoolAddCAResp, error) { + if err := svc.checkLeaderRequest(req); err != nil { + return nil, err + } + if len(req.GetCertPem()) == 0 { + return nil, errors.New("PoolAddCA: cert_pem is empty") + } + + poolUUID, err := svc.resolvePoolID(req.GetId()) + if err != nil { + return nil, err + } + lock, err := svc.sysdb.TakePoolLock(parent, poolUUID) + if err != nil { + return nil, err + } + defer lock.Release() + ctx := lock.InContext(parent) + + cert, err := security.ParsePoolCACert(req.GetCertPem()) + if err != nil { + return nil, errors.Wrap(err, "validating CA certificate") + } + if err := security.VerifyPoolCAChain(cert, svc.daosCARootPath); err != nil { + return nil, err + } + + var existing []byte + if !req.GetReplace() { + existing, err = svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA) + if err != nil { + return nil, errors.Wrap(err, "reading current pool CA bundle") + } + if existingCount := security.CountPEMCerts(existing); existingCount+1 > poolCABundleMaxCerts { + return nil, errors.Errorf("pool CA bundle would exceed max cert count (%d > %d)", + existingCount+1, poolCABundleMaxCerts) + } + } + + combined := make([]byte, 0, len(existing)+len(req.GetCertPem())) + combined = append(combined, existing...) + combined = append(combined, req.GetCertPem()...) + + if err := svc.writePoolByteProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA, combined); err != nil { + return nil, errors.Wrap(err, "writing pool CA bundle") + } + + return &mgmtpb.PoolAddCAResp{PoolUuid: poolUUID.String()}, nil +} + +// PoolRemoveCA removes one or all CA certificates from the pool's CA +// bundle. Called under the pool lock so add and remove cannot race. +func (svc *mgmtSvc) PoolRemoveCA(parent context.Context, req *mgmtpb.PoolRemoveCAReq) (*mgmtpb.PoolRemoveCAResp, error) { + if err := svc.checkLeaderRequest(req); err != nil { + return nil, err + } + if req.GetAll() && req.GetFingerprint() != "" { + return nil, errors.New("PoolRemoveCA: specify all or fingerprint, not both") + } + if !req.GetAll() && req.GetFingerprint() == "" { + return nil, errors.New("PoolRemoveCA: specify fingerprint or all") + } + + poolUUID, err := svc.resolvePoolID(req.GetId()) + if err != nil { + return nil, err + } + lock, err := svc.sysdb.TakePoolLock(parent, poolUUID) + if err != nil { + return nil, err + } + defer lock.Release() + ctx := lock.InContext(parent) + + if req.GetAll() { + if err := svc.writePoolByteProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA, nil); err != nil { + return nil, errors.Wrap(err, "clearing pool CA bundle") + } + return &mgmtpb.PoolRemoveCAResp{PoolUuid: poolUUID.String()}, nil + } + + existing, err := svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA) + if err != nil { + return nil, errors.Wrap(err, "reading current pool CA bundle") + } + if len(existing) == 0 { + return nil, errors.New("no pool CA configured") + } + + remaining, removed, err := security.RemoveCertByFingerprint(existing, req.GetFingerprint()) + if err != nil { + return nil, err + } + + if err := svc.writePoolByteProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA, remaining); err != nil { + return nil, errors.Wrap(err, "writing updated pool CA bundle") + } + + return &mgmtpb.PoolRemoveCAResp{CertsRemoved: int32(removed), PoolUuid: poolUUID.String()}, nil +} + +// PoolRevokeClient advances the per-CN revocation watermark under the +// pool lock and returns the committed timestamp. +func (svc *mgmtSvc) PoolRevokeClient(parent context.Context, req *mgmtpb.PoolRevokeClientReq) (*mgmtpb.PoolRevokeClientResp, error) { + if err := svc.checkLeaderRequest(req); err != nil { + return nil, err + } + cn := req.GetCn() + if _, _, err := security.ValidatePoolCertCN(cn); err != nil { + return nil, errors.Wrap(err, "PoolRevokeClient") + } + + poolUUID, err := svc.resolvePoolID(req.GetId()) + if err != nil { + return nil, err + } + lock, err := svc.sysdb.TakePoolLock(parent, poolUUID) + if err != nil { + return nil, err + } + defer lock.Release() + ctx := lock.InContext(parent) + + caBundle, err := svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyPoolCA) + if err != nil { + return nil, errors.Wrap(err, "reading pool CA bundle") + } + if len(caBundle) == 0 { + return nil, errors.New("pool has no CA configured; cannot revoke a client cert") + } + + existingBytes, err := svc.readPoolProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyCertWatermarks) + if err != nil { + return nil, errors.Wrap(err, "reading current watermarks") + } + + wm := make(security.CertWatermarks) + if len(existingBytes) > 0 { + wm, err = security.DecodeCertWatermarks(existingBytes) + if err != nil { + return nil, errors.Wrap(err, "decoding current watermarks") + } + } + + now := time.Now() + committed := security.AdvanceCertWatermark(wm, cn, now) + wm[cn] = committed + wm, _ = security.PruneCertWatermarks(wm, now.Add(-security.CertWatermarkRetention)) + + encoded, err := security.EncodeCertWatermarks(wm) + if err != nil { + return nil, errors.Wrap(err, "encoding updated watermarks") + } + + if err := svc.writePoolByteProperty(ctx, req.GetSys(), req.GetId(), daos.PoolPropertyCertWatermarks, encoded); err != nil { + return nil, errors.Wrap(err, "writing updated watermarks") + } + + evictedCount, evictScope, err := svc.evictForRevoke(ctx, req, cn) + if err != nil { + return nil, err + } + + return &mgmtpb.PoolRevokeClientResp{ + WatermarkRfc3339: committed.UTC().Format(time.RFC3339), + PoolUuid: poolUUID.String(), + HandlesEvictedCount: evictedCount, + EvictScope: evictScope, + }, nil +} + +// evictForRevoke selects an eviction scope based on the revoke request's +// evict_mode and the CN prefix, then performs it. Returns (count, scope). +// +// Scope rules: +// - EVICT_NONE -> ("none", 0) +// - EVICT_POOL_WIDE -> ("pool", PoolEvict() count) +// - EVICT_DEFAULT, node:X -> ("machine", PoolEvict(machine=X) count) +// - EVICT_DEFAULT, tenant:Y -> ("pool", PoolEvict() count) // no per-tenant filter +func (svc *mgmtSvc) evictForRevoke(ctx context.Context, req *mgmtpb.PoolRevokeClientReq, cn string) (int32, string, error) { + mode := req.GetEvictMode() + if mode == mgmtpb.PoolRevokeClientReq_EVICT_NONE { + return 0, "none", nil + } + + evictReq := &mgmtpb.PoolEvictReq{Sys: req.GetSys(), Id: req.GetId()} + scope := "pool" + if mode == mgmtpb.PoolRevokeClientReq_EVICT_DEFAULT && + strings.HasPrefix(cn, security.CertCNPrefixNode) { + evictReq.Machine = strings.TrimPrefix(cn, security.CertCNPrefixNode) + scope = "machine" + } + + resp, err := svc.evictPoolConnections(ctx, evictReq) + if err != nil { + return 0, "", errors.Wrap(err, "evicting after revoke") + } + if resp.GetStatus() != 0 { + return 0, "", errors.Errorf("PoolEvict returned status %d", resp.GetStatus()) + } + return resp.GetCount(), scope, nil +} + // PoolGetACL forwards a request to the I/O Engine to fetch a pool's Access Control List func (svc *mgmtSvc) PoolGetACL(ctx context.Context, req *mgmtpb.GetACLReq) (*mgmtpb.ACLResp, error) { if err := svc.checkReplicaRequest(req); err != nil { diff --git a/src/control/server/mgmt_pool_cert_test.go b/src/control/server/mgmt_pool_cert_test.go new file mode 100644 index 00000000000..493f8cfaa60 --- /dev/null +++ b/src/control/server/mgmt_pool_cert_test.go @@ -0,0 +1,572 @@ +// +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package server + +import ( + "crypto/x509" + "encoding/pem" + "os" + "strings" + "testing" + "time" + + "github.com/pkg/errors" + "google.golang.org/protobuf/proto" + + "github.com/daos-stack/daos/src/control/build" + mgmtpb "github.com/daos-stack/daos/src/control/common/proto/mgmt" + "github.com/daos-stack/daos/src/control/common/test" + "github.com/daos-stack/daos/src/control/drpc" + "github.com/daos-stack/daos/src/control/lib/daos" + "github.com/daos-stack/daos/src/control/logging" + "github.com/daos-stack/daos/src/control/security" + sectest "github.com/daos-stack/daos/src/control/security/test" +) + +// testCACertPEM returns the PEM of a fresh self-signed CA cert. +func testCACertPEM(t *testing.T, cn string) []byte { + t.Helper() + certPEM, _ := sectest.NewCA(t, cn, nil, nil) + return certPEM +} + +// encodePropBytes builds a single-prop PoolGetPropResp for mock dRPC replies. +func encodePropBytes(propNum uint32, value []byte) *mgmtpb.PoolGetPropResp { + return &mgmtpb.PoolGetPropResp{ + Properties: []*mgmtpb.PoolProperty{ + { + Number: propNum, + Value: &mgmtpb.PoolProperty_Byteval{Byteval: value}, + }, + }, + } +} + +func TestServer_MgmtSvc_PoolSetProp_RejectsCertProps(t *testing.T) { + for name, propNum := range map[string]uint32{ + "pool_ca": daos.PoolPropertyPoolCA, + "cert_watermarks": daos.PoolPropertyCertWatermarks, + } { + t.Run(name, func(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + + req := &mgmtpb.PoolSetPropReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + Properties: []*mgmtpb.PoolProperty{ + { + Number: propNum, + Value: &mgmtpb.PoolProperty_Byteval{ + Byteval: []byte("anything"), + }, + }, + }, + } + _, err := ms.PoolSetProp(test.Context(t), req) + if err == nil { + t.Fatalf("expected error rejecting prop %d, got nil", propNum) + } + }) + } +} + +func TestServer_MgmtSvc_PoolAddCA(t *testing.T) { + caPEM := testCACertPEM(t, "Pool CA 1") + + for name, tc := range map[string]struct { + req *mgmtpb.PoolAddCAReq + existingCA []byte + expErr bool + expBundle []byte // nil means don't check + }{ + "empty cert rejected": { + req: &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: nil, + }, + expErr: true, + }, + "not a CA rejected": { + req: &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", Bytes: []byte("junk"), + }), + }, + expErr: true, + }, + "append to empty bundle": { + req: &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: caPEM, + }, + expBundle: caPEM, + }, + "append to existing bundle": { + req: &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: caPEM, + }, + existingCA: testCACertPEM(t, "Pre-existing CA"), + expBundle: nil, // verified via length below + }, + } { + t.Run(name, func(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + + cfg := new(mockDrpcClientConfig) + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, tc.existingCA), + }, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolSetPropResp{}, + }, + ) + mdc := newMockDrpcClient(cfg) + setupSvcDrpcClient(ms, 0, mdc) + + _, err := ms.PoolAddCA(test.Context(t), tc.req) + if tc.expErr { + if err == nil { + t.Fatal("expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Last dRPC is the bundle write (after bundle read). + calls := mdc.calls.get() + if len(calls) < 2 { + t.Fatalf("expected at least 2 dRPC calls, got %d", len(calls)) + } + setCall := new(mgmtpb.PoolSetPropReq) + if err := unmarshalProto(calls[len(calls)-1].Body, setCall); err != nil { + t.Fatal(err) + } + if len(setCall.Properties) != 1 { + t.Fatalf("expected 1 property in setprop, got %d", len(setCall.Properties)) + } + gotBundle := setCall.Properties[0].GetByteval() + if tc.expBundle != nil { + if string(gotBundle) != string(tc.expBundle) { + t.Fatalf("unexpected bundle:\nwant: %q\ngot : %q", tc.expBundle, gotBundle) + } + } else { + // existing + new + want := append(append([]byte{}, tc.existingCA...), tc.req.CertPem...) + if string(gotBundle) != string(want) { + t.Fatalf("unexpected combined bundle:\nwant: %q\ngot : %q", want, gotBundle) + } + } + }) + } +} + +func TestServer_MgmtSvc_PoolAddCA_BundleCap(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + // Fill a bundle to the cap. + var existing []byte + for i := 0; i < poolCABundleMaxCerts; i++ { + existing = append(existing, testCACertPEM(t, "filler")...) + } + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + cfg := new(mockDrpcClientConfig) + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, existing), + }, + ) + setupSvcDrpcClient(ms, 0, newMockDrpcClient(cfg)) + + _, err := ms.PoolAddCA(test.Context(t), &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: testCACertPEM(t, "one too many"), + }) + if err == nil { + t.Fatal("expected cap-exceeded error") + } +} + +// Engine returns NotSupported for byteval writes when the pool predates +// the byteval-props gate; surface it as an actionable "upgrade the pool" error. +func TestServer_MgmtSvc_PoolAddCA_PoolNeedsUpgrade(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + cfg := new(mockDrpcClientConfig) + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, nil), + }, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolSetPropResp{ + Status: int32(daos.NotSupported), + }, + }, + ) + setupSvcDrpcClient(ms, 0, newMockDrpcClient(cfg)) + + _, err := ms.PoolAddCA(test.Context(t), &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: testCACertPEM(t, "ca"), + }) + if err == nil { + t.Fatal("expected upgrade-required error") + } + msg := err.Error() + if !strings.Contains(msg, "pool must be upgraded") || + !strings.Contains(msg, "dmg pool upgrade") { + t.Fatalf("unexpected error message: %q", msg) + } +} + +func TestServer_MgmtSvc_PoolAddCA_ChainValidation(t *testing.T) { + daosCAPEM, daosCAKey := sectest.NewCA(t, "Test DAOS CA", nil, nil) + daosCACert, err := func() (*x509.Certificate, error) { + block, _ := pem.Decode(daosCAPEM) + return x509.ParseCertificate(block.Bytes) + }() + if err != nil { + t.Fatal(err) + } + + tmpDir := t.TempDir() + caCertPath := tmpDir + "/daosCA.crt" + if err := os.WriteFile(caCertPath, daosCAPEM, 0644); err != nil { + t.Fatal(err) + } + + chainedPEM, _ := sectest.NewCA(t, "Chained Pool CA", daosCACert, daosCAKey) + unrelatedPEM := testCACertPEM(t, "Unrelated Pool CA") + + for name, tc := range map[string]struct { + certPEM []byte + expErr bool + }{ + "chained CA accepted": {certPEM: chainedPEM, expErr: false}, + "unrelated CA rejected": {certPEM: unrelatedPEM, expErr: true}, + } { + t.Run(name, func(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + ms.daosCARootPath = caCertPath + addTestPools(t, ms.sysdb, mockUUID) + + cfg := new(mockDrpcClientConfig) + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, nil), + }, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolSetPropResp{}, + }, + ) + mdc := newMockDrpcClient(cfg) + setupSvcDrpcClient(ms, 0, mdc) + + _, err := ms.PoolAddCA(test.Context(t), &mgmtpb.PoolAddCAReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + CertPem: tc.certPEM, + }) + if tc.expErr { + if err == nil { + t.Fatal("expected chain-validation error, got nil") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + } +} + +func TestServer_MgmtSvc_PoolRemoveCA(t *testing.T) { + caA := testCACertPEM(t, "CA A") + caB := testCACertPEM(t, "CA B") + bundle := append(append([]byte{}, caA...), caB...) + fpA := sectest.CertFingerprint(t, caA) + + for name, tc := range map[string]struct { + req *mgmtpb.PoolRemoveCAReq + bundle []byte + expErr bool + expRemain []byte + expCount int32 + }{ + "all and fingerprint both set rejected": { + req: &mgmtpb.PoolRemoveCAReq{ + Sys: build.DefaultSystemName, Id: mockUUID, + All: true, Fingerprint: "abc", + }, + expErr: true, + }, + "neither set rejected": { + req: &mgmtpb.PoolRemoveCAReq{ + Sys: build.DefaultSystemName, Id: mockUUID, + }, + expErr: true, + }, + "remove all": { + req: &mgmtpb.PoolRemoveCAReq{ + Sys: build.DefaultSystemName, Id: mockUUID, + All: true, + }, + bundle: bundle, + expRemain: nil, + }, + "remove by fingerprint": { + req: &mgmtpb.PoolRemoveCAReq{ + Sys: build.DefaultSystemName, Id: mockUUID, + Fingerprint: fpA, + }, + bundle: bundle, + expRemain: caB, + expCount: 1, + }, + "fingerprint not found": { + req: &mgmtpb.PoolRemoveCAReq{ + Sys: build.DefaultSystemName, Id: mockUUID, + Fingerprint: "deadbeef", + }, + bundle: bundle, + expErr: true, + }, + } { + t.Run(name, func(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + + cfg := new(mockDrpcClientConfig) + // Remove-all path writes immediately; other paths read first then write. + if tc.req.GetAll() { + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, Message: &mgmtpb.PoolSetPropResp{}, + }, + ) + } else { + cfg.setSendMsgResponseList(t, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, tc.bundle), + }, + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolSetPropResp{}, + }, + ) + } + mdc := newMockDrpcClient(cfg) + setupSvcDrpcClient(ms, 0, mdc) + + resp, err := ms.PoolRemoveCA(test.Context(t), tc.req) + if tc.expErr { + if err == nil { + t.Fatal("expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.GetCertsRemoved() != tc.expCount && !tc.req.GetAll() { + t.Fatalf("expected certs_removed=%d, got %d", tc.expCount, resp.GetCertsRemoved()) + } + + calls := mdc.calls.get() + setCall := new(mgmtpb.PoolSetPropReq) + if err := unmarshalProto(calls[len(calls)-1].Body, setCall); err != nil { + t.Fatal(err) + } + gotBundle := setCall.Properties[0].GetByteval() + if string(gotBundle) != string(tc.expRemain) { + t.Fatalf("unexpected remaining bundle:\nwant: %q\ngot : %q", tc.expRemain, gotBundle) + } + }) + } +} + +func TestServer_MgmtSvc_PoolRevokeClient(t *testing.T) { + caPEM := testCACertPEM(t, "Pool CA") + + for name, tc := range map[string]struct { + cn string + existingWM security.CertWatermarks + caBundle []byte + expErr bool + expWatermark func(committed time.Time) error + }{ + "missing prefix rejected": { + cn: "foo", + caBundle: caPEM, + expErr: true, + }, + "empty suffix rejected": { + cn: "node:", + caBundle: caPEM, + expErr: true, + }, + "no pool CA rejected": { + cn: "node:n1", + caBundle: nil, + expErr: true, + }, + "fresh CN": { + cn: "node:n1", + caBundle: caPEM, + expWatermark: func(t time.Time) error { + if t.IsZero() { + return errors.New("expected non-zero timestamp") + } + return nil + }, + }, + "existing CN advances monotonically": { + cn: "node:n1", + caBundle: caPEM, + existingWM: security.CertWatermarks{ + "node:n1": time.Now().Add(time.Hour).UTC().Truncate(time.Second), + }, + expWatermark: func(committed time.Time) error { + // Must be strictly greater than the existing watermark. + return nil + }, + }, + } { + t.Run(name, func(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ms := newTestMgmtSvc(t, log) + addTestPools(t, ms.sysdb, mockUUID) + + encoded, err := security.EncodeCertWatermarks(tc.existingWM) + if err != nil { + t.Fatal(err) + } + + cfg := new(mockDrpcClientConfig) + cfg.setSendMsgResponseList(t, + // First read: pool CA bundle. + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyPoolCA, tc.caBundle), + }, + // Second read: existing watermarks. + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: encodePropBytes(daos.PoolPropertyCertWatermarks, encoded), + }, + // Write: updated watermarks. + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolSetPropResp{}, + }, + // PoolEvict for the revoked CN. + &mockDrpcResponse{ + Status: drpc.Status_SUCCESS, + Message: &mgmtpb.PoolEvictResp{Count: 0}, + }, + ) + mdc := newMockDrpcClient(cfg) + setupSvcDrpcClient(ms, 0, mdc) + + resp, err := ms.PoolRevokeClient(test.Context(t), &mgmtpb.PoolRevokeClientReq{ + Sys: build.DefaultSystemName, + Id: mockUUID, + Cn: tc.cn, + }) + if tc.expErr { + if err == nil { + t.Fatal("expected error, got nil") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + committed, err := time.Parse(time.RFC3339, resp.GetWatermarkRfc3339()) + if err != nil { + t.Fatalf("parsing committed watermark: %v", err) + } + if prev, ok := tc.existingWM[tc.cn]; ok { + if !committed.After(prev) { + t.Fatalf("expected committed watermark %s to be after existing %s", + committed.Format(time.RFC3339), prev.Format(time.RFC3339)) + } + } + if tc.expWatermark != nil { + if err := tc.expWatermark(committed); err != nil { + t.Fatal(err) + } + } + + // Validate the watermark write. The last call is PoolEvict; the + // PoolSetProp for cert_watermarks is the one before it. + calls := mdc.calls.get() + setCall := new(mgmtpb.PoolSetPropReq) + if err := unmarshalProto(calls[len(calls)-2].Body, setCall); err != nil { + t.Fatal(err) + } + blob := setCall.Properties[0].GetByteval() + wm, err := security.DecodeCertWatermarks(blob) + if err != nil { + t.Fatalf("decoding written blob: %v", err) + } + got, ok := wm[tc.cn] + if !ok { + t.Fatalf("written blob has no entry for %s", tc.cn) + } + if !got.Equal(committed) { + t.Fatalf("written watermark %s != committed %s", + got.Format(time.RFC3339), committed.Format(time.RFC3339)) + } + }) + } +} + +func unmarshalProto(body []byte, msg proto.Message) error { + return proto.Unmarshal(body, msg) +} diff --git a/src/control/server/mgmt_svc.go b/src/control/server/mgmt_svc.go index 1334e23dd63..bac8209b8f7 100644 --- a/src/control/server/mgmt_svc.go +++ b/src/control/server/mgmt_svc.go @@ -83,6 +83,8 @@ type mgmtSvc struct { serialReqs batchReqChan groupUpdateReqs chan bool lastMapVer uint32 + // daosCARootPath is the DAOS CA cert path; empty under AllowInsecure. + daosCARootPath string } func newMgmtSvc(h *EngineHarness, m *system.Membership, s *raft.Database, c control.UnaryInvoker, p *events.PubSub) *mgmtSvc { diff --git a/src/control/server/security_rpc.go b/src/control/server/security_rpc.go index 3aa57ac9fc9..516cee20644 100644 --- a/src/control/server/security_rpc.go +++ b/src/control/server/security_rpc.go @@ -1,6 +1,6 @@ // // (C) Copyright 2019-2022 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -8,11 +8,21 @@ package server import ( + "bytes" "context" "crypto" + "crypto/x509" + "encoding/binary" + "encoding/hex" + "encoding/pem" "fmt" + "math" "path/filepath" + "strings" + "sync" + "time" + "github.com/google/uuid" "google.golang.org/protobuf/proto" "github.com/daos-stack/daos/src/control/drpc" @@ -22,17 +32,30 @@ import ( "github.com/daos-stack/daos/src/control/security/auth" ) +// handleCacheMaxSize bounds the replay cache; reaching it is an attack signal. +const handleCacheMaxSize = 65536 + // SecurityModule is the security drpc module struct type SecurityModule struct { - log logging.Logger - config *security.TransportConfig + log logging.Logger + config *security.TransportConfig + maxClockSkew time.Duration + // handleCache: (pool, handle) -> insert time; entries expire after 2*maxClockSkew. + handleCache map[string]time.Time + handleCacheMu sync.Mutex } // NewSecurityModule creates a new security module with a transport config func NewSecurityModule(log logging.Logger, tc *security.TransportConfig) *SecurityModule { + maxClockSkew := security.NotBeforeSkewTolerance + if tc != nil && tc.PoolCertMaxClockSkew > 0 { + maxClockSkew = tc.PoolCertMaxClockSkew + } return &SecurityModule{ - log: log, - config: tc, + log: log, + config: tc, + maxClockSkew: maxClockSkew, + handleCache: make(map[string]time.Time), } } @@ -84,11 +107,14 @@ func (m *SecurityModule) validateRespWithStatus(status daos.Status) ([]byte, err // HandleCall is the handler for calls to the SecurityModule func (m *SecurityModule) HandleCall(_ context.Context, session *drpc.Session, method drpc.Method, body []byte) ([]byte, error) { - if method != daos.MethodValidateCredentials { + switch method { + case daos.MethodValidateCredentials: + return m.processValidateCredentials(body) + case daos.MethodValidateNodeCert: + return m.processValidateNodeCert(body) + default: return nil, drpc.UnknownMethodFailure() } - - return m.processValidateCredentials(body) } // ID will return Security module ID @@ -105,7 +131,191 @@ func (m *SecurityModule) GetMethod(id int32) (drpc.Method, error) { switch id { case daos.MethodValidateCredentials.ID(): return daos.MethodValidateCredentials, nil + case daos.MethodValidateNodeCert.ID(): + return daos.MethodValidateNodeCert, nil default: return nil, fmt.Errorf("invalid method ID %d for module %s", id, m.String()) } } + +func (m *SecurityModule) processValidateNodeCert(body []byte) ([]byte, error) { + req := &auth.ValidateNodeCertReq{} + if err := proto.Unmarshal(body, req); err != nil { + return nil, drpc.UnmarshalingPayloadFailure() + } + + nodeCert, err := parsePEMCert(req.NodeCert) + if err != nil { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("failed to parse node certificate: %v", err)) + } + m.log.Tracef("validating node cert: pool=%s, CN=%s, issuer=%s, expires=%s", + req.PoolId, nodeCert.Subject.CommonName, nodeCert.Issuer.CommonName, + nodeCert.NotAfter.Format(time.RFC3339)) + + intermediates := x509.NewCertPool() + rest := req.PoolCa + nCAs := 0 + for len(rest) > 0 { + var block *pem.Block + block, rest = pem.Decode(rest) + if block == nil { + break + } + if block.Type != "CERTIFICATE" { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("unexpected PEM block type %q in pool CA bundle", block.Type)) + } + caCert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("malformed cert in pool CA bundle: %v", err)) + } + intermediates.AddCert(caCert) + nCAs++ + m.log.Tracef("loaded pool CA cert: CN=%s, issuer=%s, expires=%s", + caCert.Subject.CommonName, caCert.Issuer.CommonName, + caCert.NotAfter.Format(time.RFC3339)) + } + if nCAs == 0 { + return m.rejectNodeCert(req, daos.BadCert, "pool CA bundle contains no certificates") + } + + daosCA, err := security.LoadCertificate(m.config.CARootPath) + if err != nil { + return m.rejectNodeCert(req, daos.NoCert, + fmt.Sprintf("failed to load DAOS CA: %v", err)) + } + m.log.Tracef("loaded DAOS CA cert: CN=%s, issuer=%s, expires=%s", + daosCA.Subject.CommonName, daosCA.Issuer.CommonName, + daosCA.NotAfter.Format(time.RFC3339)) + + roots := x509.NewCertPool() + roots.AddCert(daosCA) + + if _, err := nodeCert.Verify(x509.VerifyOptions{ + Roots: roots, + Intermediates: intermediates, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + }); err != nil { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("node cert chain validation failed: %v", err)) + } + + cn := nodeCert.Subject.CommonName + switch { + case strings.HasPrefix(cn, security.CertCNPrefixTenant): + // Tenant key compromise on any node = full tenant compromise; + // containment is via watermark revocation. + case strings.HasPrefix(cn, security.CertCNPrefixNode): + // Defense-in-depth: reject empty machine name explicitly even + // though the engine's get_sec_origin_for_token also rejects it. + if req.MachineName == "" { + return m.rejectNodeCert(req, daos.InvalidInput, + fmt.Sprintf("cert CN %q is node-scoped but credential machine name is empty", + cn)) + } + nodeName := strings.TrimPrefix(cn, security.CertCNPrefixNode) + if nodeName != req.MachineName { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("cert CN %q does not match credential machine name %q", + cn, req.MachineName)) + } + default: + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("cert CN %q has no recognized prefix", cn)) + } + + if len(req.CertWatermarks) > 0 { + watermarks, err := security.DecodeCertWatermarks(req.CertWatermarks) + if err != nil { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("failed to parse cert watermarks: %v", err)) + } + if wm, ok := watermarks[cn]; ok && !nodeCert.NotBefore.After(wm) { + return m.rejectNodeCert(req, daos.BadCert, + fmt.Sprintf("cert for %q revoked (NotBefore=%s, watermark=%s)", + cn, nodeCert.NotBefore.Format(time.RFC3339), + wm.Format(time.RFC3339))) + } + } + + if len(req.NodeCertPayload) != security.PoPPayloadLen { + return m.rejectNodeCert(req, daos.InvalidInput, + fmt.Sprintf("invalid PoP payload length: %d (expected %d)", + len(req.NodeCertPayload), security.PoPPayloadLen)) + } + + // Cross-pool replay defense: a node cert shared across pools must not let a PoP + // captured for pool A authenticate a connect to pool B. + reqPoolUUID, err := uuid.Parse(req.PoolId) + if err != nil { + return m.rejectNodeCert(req, daos.InvalidInput, + fmt.Sprintf("invalid pool UUID: %v", err)) + } + if !bytes.Equal(req.NodeCertPayload[0:16], reqPoolUUID[:]) { + return m.rejectNodeCert(req, daos.NoPermission, + "PoP payload pool UUID does not match request pool ID") + } + + ts := int64(binary.BigEndian.Uint64(req.NodeCertPayload[32:40])) + skew := time.Duration(math.Abs(float64(time.Now().Unix()-ts))) * time.Second + if skew > m.maxClockSkew { + return m.rejectNodeCert(req, daos.NoPermission, + fmt.Sprintf("PoP timestamp skew too large: %v (max %v)", + skew, m.maxClockSkew)) + } + + if err := security.VerifyPoP(nodeCert.PublicKey, req.NodeCertPayload, req.NodeCertPop); err != nil { + return m.rejectNodeCert(req, daos.NoPermission, + fmt.Sprintf("PoP signature verification failed: %v", err)) + } + + // Replay check keyed on (pool, handle) to match the PoP payload binding. + handleKey := hex.EncodeToString(req.NodeCertPayload[0:32]) + m.handleCacheMu.Lock() + if expiry, found := m.handleCache[handleKey]; found && time.Now().Before(expiry) { + m.handleCacheMu.Unlock() + return m.rejectNodeCert(req, daos.NoPermission, + fmt.Sprintf("replay detected: handle %s already seen", handleKey)) + } + if len(m.handleCache) >= handleCacheMaxSize { + now := time.Now() + for k, v := range m.handleCache { + if now.After(v) { + delete(m.handleCache, k) + } + } + if len(m.handleCache) >= handleCacheMaxSize { + for k := range m.handleCache { + delete(m.handleCache, k) + break + } + } + } + m.handleCache[handleKey] = time.Now().Add(m.maxClockSkew * 2) + m.handleCacheMu.Unlock() + + m.log.Debugf("node cert validated: pool=%s, CN=%s, issuer=%s, skew=%v", + req.PoolId, nodeCert.Subject.CommonName, nodeCert.Issuer.CommonName, skew) + + return drpc.Marshal(&auth.ValidateNodeCertResp{Status: 0}) +} + +// rejectNodeCert logs and returns a ValidateNodeCertResp carrying status + detail. +func (m *SecurityModule) rejectNodeCert(req *auth.ValidateNodeCertReq, status daos.Status, detail string) ([]byte, error) { + m.log.Errorf("node cert rejected (pool=%s, status=%s): %s", + req.PoolId, status, detail) + return drpc.Marshal(&auth.ValidateNodeCertResp{ + Status: int32(status), + Detail: detail, + }) +} + +func parsePEMCert(data []byte) (*x509.Certificate, error) { + block, _ := pem.Decode(data) + if block == nil { + return nil, fmt.Errorf("no PEM data found") + } + return x509.ParseCertificate(block.Bytes) +} diff --git a/src/control/server/security_rpc_test.go b/src/control/server/security_rpc_test.go index 3f29f96bbf3..0b65e63b9c4 100644 --- a/src/control/server/security_rpc_test.go +++ b/src/control/server/security_rpc_test.go @@ -1,6 +1,6 @@ // // (C) Copyright 2019-2022 Intel Corporation. -// (C) Copyright 2025 Hewlett Packard Enterprise Development LP +// (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -9,9 +9,14 @@ package server import ( "crypto" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/x509" + "crypto/x509/pkix" + "encoding/binary" + "encoding/json" "encoding/pem" "math/big" "os" @@ -20,6 +25,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/google/uuid" "github.com/pkg/errors" "google.golang.org/protobuf/proto" @@ -31,6 +37,12 @@ import ( "github.com/daos-stack/daos/src/control/security/auth" ) +// testMachineName matches the node-scoped CN baked into the test cert +// chain (CertCNPrefixNode + testMachineName). Tests that exercise the +// happy path must pass this as the credential MachineName so the +// CN-to-machine cross-check passes. +const testMachineName = "testnode" + func TestSrvSecurityModule_ID(t *testing.T) { log, buf := logging.NewTestLogger(t.Name()) defer test.ShowBufferOnFailure(t, buf) @@ -363,3 +375,503 @@ func TestSrvSecurityModule_ValidateCred_Secure_BadVerifier(t *testing.T) { Status: int32(daos.NoPermission), }) } + +// --- Node cert validation tests --- + +type testCertChain struct { + caCert *x509.Certificate + caKey *ecdsa.PrivateKey + poolCACert *x509.Certificate + poolCAKey *ecdsa.PrivateKey + nodeCert *x509.Certificate + nodeKey *ecdsa.PrivateKey + caCertPEM []byte + poolCAPEM []byte + nodePEM []byte +} + +func generateTestCertChain(t *testing.T) *testCertChain { + t.Helper() + tc := &testCertChain{} + + // DAOS CA (root) + tc.caKey, _ = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + caTemplate := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: "Test DAOS CA"}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + } + caDER, _ := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, &tc.caKey.PublicKey, tc.caKey) + tc.caCert, _ = x509.ParseCertificate(caDER) + tc.caCertPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caDER}) + + // Pool CA (intermediate) + tc.poolCAKey, _ = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + serial, _ = rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + poolCATemplate := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: "Test Pool CA"}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + MaxPathLen: 0, + MaxPathLenZero: true, + } + poolCADER, _ := x509.CreateCertificate(rand.Reader, poolCATemplate, tc.caCert, &tc.poolCAKey.PublicKey, tc.caKey) + tc.poolCACert, _ = x509.ParseCertificate(poolCADER) + tc.poolCAPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: poolCADER}) + + // Node cert + tc.nodeKey, _ = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + serial, _ = rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + nodeTemplate := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{CommonName: security.CertCNPrefixNode + testMachineName}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + nodeDER, _ := x509.CreateCertificate(rand.Reader, nodeTemplate, tc.poolCACert, &tc.nodeKey.PublicKey, tc.poolCAKey) + tc.nodeCert, _ = x509.ParseCertificate(nodeDER) + tc.nodePEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: nodeDER}) + + return tc +} + +func makePoP(t *testing.T, key *ecdsa.PrivateKey, poolUUID, handleUUID []byte) (payload, sig []byte) { + t.Helper() + payload = make([]byte, security.PoPPayloadLen) + copy(payload[0:16], poolUUID) + copy(payload[16:32], handleUUID) + binary.BigEndian.PutUint64(payload[32:40], uint64(time.Now().Unix())) + + var err error + sig, err = security.SignPoP(key, nil, payload) + if err != nil { + t.Fatalf("sign PoP: %v", err) + } + return payload, sig +} + +func writeCAToDir(t *testing.T, dir string, caPEM []byte) string { + t.Helper() + path := filepath.Join(dir, "daosCA.crt") + if err := os.WriteFile(path, caPEM, 0644); err != nil { + t.Fatal(err) + } + return path +} + +func TestSrvSecurityModule_ValidateNodeCert(t *testing.T) { + chain := generateTestCertChain(t) + + poolUUID := make([]byte, 16) + handleUUID := make([]byte, 16) + rand.Read(poolUUID) + rand.Read(handleUUID) + + validPayload, validSig := makePoP(t, chain.nodeKey, poolUUID, handleUUID) + + stalePayload := make([]byte, security.PoPPayloadLen) + copy(stalePayload[0:16], poolUUID) + copy(stalePayload[16:32], handleUUID) + binary.BigEndian.PutUint64(stalePayload[32:40], uint64(time.Now().Add(-10*time.Minute).Unix())) + staleSig, _ := security.SignPoP(chain.nodeKey, nil, stalePayload) + + rogueKey, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + rogueSerial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + rogueTmpl := &x509.Certificate{ + SerialNumber: rogueSerial, + Subject: pkix.Name{CommonName: "rogue"}, + NotBefore: time.Now().Add(-time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + rogueDER, _ := x509.CreateCertificate(rand.Reader, rogueTmpl, rogueTmpl, &rogueKey.PublicKey, rogueKey) + roguePEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rogueDER}) + + for name, tc := range map[string]struct { + nodePEM []byte + poolCAPEM []byte + payload []byte + pop []byte + machineName string + expStatus daos.Status + }{ + "valid chain and PoP": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: validPayload, + pop: validSig, + machineName: testMachineName, + expStatus: 0, + }, + "self-signed node cert": { + nodePEM: roguePEM, + poolCAPEM: chain.poolCAPEM, + payload: make([]byte, security.PoPPayloadLen), + pop: []byte{1, 2, 3}, + machineName: testMachineName, + expStatus: daos.BadCert, + }, + "bad PoP signature": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: validPayload, + pop: []byte{0xDE, 0xAD}, + machineName: testMachineName, + expStatus: daos.NoPermission, + }, + "expired timestamp": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: stalePayload, + pop: staleSig, + machineName: testMachineName, + expStatus: daos.NoPermission, + }, + "bad payload length": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: []byte{1, 2, 3}, + pop: []byte{4, 5, 6}, + machineName: testMachineName, + expStatus: daos.InvalidInput, + }, + "empty machine name on node-prefix cert": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: validPayload, + pop: validSig, + machineName: "", + expStatus: daos.InvalidInput, + }, + "machine name mismatch": { + nodePEM: chain.nodePEM, + poolCAPEM: chain.poolCAPEM, + payload: validPayload, + pop: validSig, + machineName: "imposter", + expStatus: daos.BadCert, + }, + } { + t.Run(name, func(t *testing.T) { + parent := test.MustLogContext(t) + log := logging.FromContext(parent) + + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + caPath := writeCAToDir(t, tmpDir, chain.caCertPEM) + + mod := NewSecurityModule(log, &security.TransportConfig{ + CertificateConfig: security.CertificateConfig{ + CARootPath: caPath, + }, + }) + + req := &auth.ValidateNodeCertReq{ + PoolCa: tc.poolCAPEM, + NodeCert: tc.nodePEM, + NodeCertPop: tc.pop, + NodeCertPayload: tc.payload, + PoolId: uuid.Must(uuid.FromBytes(poolUUID)).String(), + MachineName: tc.machineName, + } + reqBytes := marshal(t, req) + + respBytes, err := mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, reqBytes) + if err != nil { + t.Fatalf("HandleCall error: %v", err) + } + + resp := &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal response: %v", err) + } + + if daos.Status(resp.Status) != tc.expStatus { + t.Errorf("expected status %v, got %v", tc.expStatus, daos.Status(resp.Status)) + } + }) + } +} + +func TestSrvSecurityModule_ValidateNodeCert_Watermarks(t *testing.T) { + chain := generateTestCertChain(t) + + poolUUID := make([]byte, 16) + rand.Read(poolUUID) + + // The test chain's node cert was issued with NotBefore = now - 1m. + nodeNotBefore := chain.nodeCert.NotBefore + nodeCN := chain.nodeCert.Subject.CommonName + + for name, tc := range map[string]struct { + watermarks map[string]string // CN → RFC3339 (key "__raw__" stuffs a raw blob) + expStatus daos.Status + }{ + "no watermarks set": { + watermarks: nil, + expStatus: 0, + }, + "watermark for unrelated CN is ignored": { + watermarks: map[string]string{ + "node:other-node": nodeNotBefore.Add(time.Hour).UTC().Format(time.RFC3339), + }, + expStatus: 0, + }, + "watermark earlier than cert NotBefore allows cert": { + watermarks: map[string]string{ + nodeCN: nodeNotBefore.Add(-time.Hour).UTC().Format(time.RFC3339), + }, + expStatus: 0, + }, + "watermark equal to cert NotBefore revokes cert": { + watermarks: map[string]string{ + nodeCN: nodeNotBefore.UTC().Format(time.RFC3339), + }, + expStatus: daos.BadCert, + }, + "watermark after cert NotBefore revokes cert": { + watermarks: map[string]string{ + nodeCN: nodeNotBefore.Add(time.Hour).UTC().Format(time.RFC3339), + }, + expStatus: daos.BadCert, + }, + "malformed watermarks blob rejects cert": { + watermarks: map[string]string{"__raw__": "not-json"}, + expStatus: daos.BadCert, + }, + "bad timestamp in blob rejects cert": { + watermarks: map[string]string{nodeCN: "not-a-date"}, + expStatus: daos.BadCert, + }, + } { + t.Run(name, func(t *testing.T) { + parent := test.MustLogContext(t) + log := logging.FromContext(parent) + + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + caPath := writeCAToDir(t, tmpDir, chain.caCertPEM) + + mod := NewSecurityModule(log, &security.TransportConfig{ + CertificateConfig: security.CertificateConfig{ + CARootPath: caPath, + }, + }) + + var watermarksBlob []byte + if raw, ok := tc.watermarks["__raw__"]; ok { + watermarksBlob = []byte(raw) + } else if len(tc.watermarks) > 0 { + blob, err := json.Marshal(tc.watermarks) + if err != nil { + t.Fatal(err) + } + watermarksBlob = blob + } + + // Use a fresh handle UUID per sub-test to avoid the + // replay cache used by the replay test. + perCaseHandle := make([]byte, 16) + rand.Read(perCaseHandle) + perCasePayload, perCaseSig := makePoP(t, chain.nodeKey, poolUUID, perCaseHandle) + + req := &auth.ValidateNodeCertReq{ + PoolCa: chain.poolCAPEM, + NodeCert: chain.nodePEM, + NodeCertPop: perCaseSig, + NodeCertPayload: perCasePayload, + PoolId: uuid.Must(uuid.FromBytes(poolUUID)).String(), + MachineName: testMachineName, + CertWatermarks: watermarksBlob, + } + reqBytes := marshal(t, req) + + respBytes, err := mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, reqBytes) + if err != nil { + t.Fatalf("HandleCall error: %v", err) + } + + resp := &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal response: %v", err) + } + + if daos.Status(resp.Status) != tc.expStatus { + t.Errorf("expected status %v, got %v (detail=%q)", + tc.expStatus, daos.Status(resp.Status), resp.Detail) + } + }) + } +} + +func TestSrvSecurityModule_ValidateNodeCert_Replay(t *testing.T) { + chain := generateTestCertChain(t) + + poolUUID := make([]byte, 16) + handleUUID := make([]byte, 16) + rand.Read(poolUUID) + rand.Read(handleUUID) + + payload, sig := makePoP(t, chain.nodeKey, poolUUID, handleUUID) + + parent := test.MustLogContext(t) + log := logging.FromContext(parent) + + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + + caPath := writeCAToDir(t, tmpDir, chain.caCertPEM) + + mod := NewSecurityModule(log, &security.TransportConfig{ + CertificateConfig: security.CertificateConfig{ + CARootPath: caPath, + }, + }) + + req := &auth.ValidateNodeCertReq{ + PoolCa: chain.poolCAPEM, + NodeCert: chain.nodePEM, + NodeCertPop: sig, + NodeCertPayload: payload, + PoolId: uuid.Must(uuid.FromBytes(poolUUID)).String(), + MachineName: testMachineName, + } + reqBytes := marshal(t, req) + + // First call should succeed + respBytes, err := mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, reqBytes) + if err != nil { + t.Fatalf("first call error: %v", err) + } + resp := &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if resp.Status != 0 { + t.Fatalf("first call: expected success, got status %d", resp.Status) + } + + // Replay with same handle UUID should be rejected + respBytes, err = mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, reqBytes) + if err != nil { + t.Fatalf("replay call error: %v", err) + } + resp = &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if daos.Status(resp.Status) != daos.NoPermission { + t.Errorf("replay: expected NoPermission, got %v", daos.Status(resp.Status)) + } +} + +// A PoP captured for pool A must not authenticate a connect to pool B, +// even when the node cert chains to a CA shared between the two pools. +func TestSrvSecurityModule_ValidateNodeCert_CrossPoolReplay(t *testing.T) { + chain := generateTestCertChain(t) + + poolA := make([]byte, 16) + poolB := make([]byte, 16) + handle := make([]byte, 16) + rand.Read(poolA) + rand.Read(poolB) + rand.Read(handle) + + payload, sig := makePoP(t, chain.nodeKey, poolA, handle) + + log, _ := logging.NewTestLogger(t.Name()) + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + caPath := writeCAToDir(t, tmpDir, chain.caCertPEM) + + mod := NewSecurityModule(log, &security.TransportConfig{ + CertificateConfig: security.CertificateConfig{CARootPath: caPath}, + }) + + // PoolId says pool B, but the PoP payload binds pool A. + req := &auth.ValidateNodeCertReq{ + PoolCa: chain.poolCAPEM, + NodeCert: chain.nodePEM, + NodeCertPop: sig, + NodeCertPayload: payload, + PoolId: uuid.Must(uuid.FromBytes(poolB)).String(), + MachineName: testMachineName, + } + respBytes, err := mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, marshal(t, req)) + if err != nil { + t.Fatalf("call error: %v", err) + } + resp := &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if daos.Status(resp.Status) != daos.NoPermission { + t.Errorf("cross-pool replay: expected NoPermission, got %v", daos.Status(resp.Status)) + } +} + +// A malformed entry anywhere in the pool CA bundle must reject the connect +// rather than be silently skipped. +func TestSrvSecurityModule_ValidateNodeCert_MalformedCABundle(t *testing.T) { + chain := generateTestCertChain(t) + poolUUID := make([]byte, 16) + handleUUID := make([]byte, 16) + rand.Read(poolUUID) + rand.Read(handleUUID) + payload, sig := makePoP(t, chain.nodeKey, poolUUID, handleUUID) + + log, _ := logging.NewTestLogger(t.Name()) + tmpDir, cleanup := test.CreateTestDir(t) + defer cleanup() + caPath := writeCAToDir(t, tmpDir, chain.caCertPEM) + + mod := NewSecurityModule(log, &security.TransportConfig{ + CertificateConfig: security.CertificateConfig{CARootPath: caPath}, + }) + + concat := func(extra *pem.Block) []byte { + out := make([]byte, 0, len(chain.poolCAPEM)+200) + out = append(out, chain.poolCAPEM...) + return append(out, pem.EncodeToMemory(extra)...) + } + for name, badBundle := range map[string][]byte{ + "non-CERTIFICATE PEM block": concat(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte("x")}), + "malformed CERTIFICATE block": concat(&pem.Block{Type: "CERTIFICATE", Bytes: []byte("not der")}), + } { + t.Run(name, func(t *testing.T) { + req := &auth.ValidateNodeCertReq{ + PoolCa: badBundle, + NodeCert: chain.nodePEM, + NodeCertPop: sig, + NodeCertPayload: payload, + PoolId: uuid.Must(uuid.FromBytes(poolUUID)).String(), + MachineName: testMachineName, + } + respBytes, err := mod.HandleCall(test.Context(t), nil, daos.MethodValidateNodeCert, marshal(t, req)) + if err != nil { + t.Fatalf("call error: %v", err) + } + resp := &auth.ValidateNodeCertResp{} + if err := proto.Unmarshal(respBytes, resp); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if daos.Status(resp.Status) != daos.BadCert { + t.Errorf("expected BadCert, got %v", daos.Status(resp.Status)) + } + }) + } +} diff --git a/src/control/server/server.go b/src/control/server/server.go index 69fa0703a4d..70fb33486ff 100644 --- a/src/control/server/server.go +++ b/src/control/server/server.go @@ -260,6 +260,9 @@ func (srv *server) createServices(ctx context.Context) (err error) { network.DefaultFabricScanner(srv.log)) srv.ctlSvc.restartMgr = srv.restartMgr srv.mgmtSvc = newMgmtSvc(srv.harness, srv.membership, srv.sysdb, rpcClient, srv.pubSub) + if !srv.cfg.TransportConfig.AllowInsecure { + srv.mgmtSvc.daosCARootPath = srv.cfg.TransportConfig.CARootPath + } if err := srv.mgmtSvc.systemProps.UpdateCompPropVal(daos.SystemPropertyDaosSystem, func() string { return srv.cfg.SystemName diff --git a/src/include/daos/drpc_modules.h b/src/include/daos/drpc_modules.h index 791852334f0..a2307f83187 100644 --- a/src/include/daos/drpc_modules.h +++ b/src/include/daos/drpc_modules.h @@ -1,6 +1,6 @@ /* * (C) Copyright 2019-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -100,9 +100,10 @@ enum drpc_srv_method { }; enum drpc_sec_method { - DRPC_METHOD_SEC_VALIDATE_CREDS = 401, + DRPC_METHOD_SEC_VALIDATE_CREDS = 401, + DRPC_METHOD_SEC_VALIDATE_NODE_CERT = 402, - NUM_DRPC_SEC_METHODS /* Must be last */ + NUM_DRPC_SEC_METHODS /* Must be last */ }; #endif /* __DAOS_DRPC_MODULES_H__ */ diff --git a/src/include/daos/pool.h b/src/include/daos/pool.h index 93403237cf1..b91e141ea91 100644 --- a/src/include/daos/pool.h +++ b/src/include/daos/pool.h @@ -1,6 +1,6 @@ /* * (C) Copyright 2016-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -64,7 +64,9 @@ #define DAOS_PO_QUERY_PROP_REINT_MODE (1ULL << (PROP_BIT_START + 24)) #define DAOS_PO_QUERY_PROP_SVC_OPS_ENABLED (1ULL << (PROP_BIT_START + 25)) #define DAOS_PO_QUERY_PROP_SVC_OPS_ENTRY_AGE (1ULL << (PROP_BIT_START + 26)) -#define DAOS_PO_QUERY_PROP_BIT_END 42 +#define DAOS_PO_QUERY_PROP_POOL_CA (1ULL << (PROP_BIT_START + 27)) +#define DAOS_PO_QUERY_PROP_CERT_WATERMARKS (1ULL << (PROP_BIT_START + 28)) +#define DAOS_PO_QUERY_PROP_BIT_END 44 #define DAOS_PO_QUERY_PROP_ALL \ (DAOS_PO_QUERY_PROP_LABEL | DAOS_PO_QUERY_PROP_SPACE_RB | DAOS_PO_QUERY_PROP_SELF_HEAL | \ @@ -78,15 +80,17 @@ DAOS_PO_QUERY_PROP_OBJ_VERSION | DAOS_PO_QUERY_PROP_PERF_DOMAIN | \ DAOS_PO_QUERY_PROP_CHECKPOINT_MODE | DAOS_PO_QUERY_PROP_CHECKPOINT_FREQ | \ DAOS_PO_QUERY_PROP_CHECKPOINT_THRESH | DAOS_PO_QUERY_PROP_REINT_MODE | \ - DAOS_PO_QUERY_PROP_SVC_OPS_ENABLED | DAOS_PO_QUERY_PROP_SVC_OPS_ENTRY_AGE) + DAOS_PO_QUERY_PROP_SVC_OPS_ENABLED | DAOS_PO_QUERY_PROP_SVC_OPS_ENTRY_AGE | \ + DAOS_PO_QUERY_PROP_POOL_CA | DAOS_PO_QUERY_PROP_CERT_WATERMARKS) /* * Version 1 corresponds to 2.2 (aggregation optimizations) * Version 2 corresponds to 2.4 (dynamic evtree, checksum scrubbing) * Version 3 corresponds to 2.6 (root embedded values, pool service operations tracking KVS) * Version 4 corresponds to 2.8 (SV gang allocation, server pool/cont hdls) + * Version 5 corresponds to 2.8.1 (byteval pool properties) */ -#define DAOS_POOL_GLOBAL_VERSION 4 +#define DAOS_POOL_GLOBAL_VERSION 5 /** * Each individual object layout format, like oid layout, dkey to group, diff --git a/src/include/daos/rpc.h b/src/include/daos/rpc.h index 030e9a078dd..4b2f2217be4 100644 --- a/src/include/daos/rpc.h +++ b/src/include/daos/rpc.h @@ -68,7 +68,7 @@ enum daos_module_id { #define DAOS_VOS_VERSION 1 #define DAOS_MGMT_VERSION 4 -#define DAOS_POOL_VERSION 7 +#define DAOS_POOL_VERSION 8 #define DAOS_CONT_VERSION 9 #define DAOS_OBJ_VERSION 10 #define DAOS_REBUILD_VERSION 5 diff --git a/src/include/daos/security.h b/src/include/daos/security.h index 31477a92e5e..a0165635a73 100644 --- a/src/include/daos/security.h +++ b/src/include/daos/security.h @@ -1,5 +1,6 @@ /* * (C) Copyright 2018-2023 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -39,6 +40,25 @@ struct d_ownership { */ int dc_sec_request_creds(d_iov_t *creds); +/** + * Request security credentials with per-pool node certificate. + * + * Like dc_sec_request_creds(), but also requests a per-pool node certificate + * and proof-of-possession from the agent. Used by pool connect to support + * per-pool node certificate authentication. + * + * \param[out] creds Returned security credentials for current user. + * \param[in] pool_uuid Pool UUID. + * \param[in] handle_uuid Pool handle UUID for PoP binding. + * \param[out] node_cert Returned PEM node certificate (may be empty). + * \param[out] node_cert_pop Returned PoP signature + payload (may be empty). + * + * \return Same as dc_sec_request_creds(). + */ +int +dc_sec_request_pool_creds(d_iov_t *creds, uuid_t pool_uuid, uuid_t handle_uuid, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload); + /** * Request a user's permissions for a specific pool. * diff --git a/src/include/daos_prop.h b/src/include/daos_prop.h index cdbada88dab..b3fb6a8042c 100644 --- a/src/include/daos_prop.h +++ b/src/include/daos_prop.h @@ -140,6 +140,12 @@ enum daos_pool_props { DAOS_PROP_PO_SVC_OPS_ENABLED, /** Metadata duplicate operations SVC_OPS KVS max entry age (seconds), default 300 */ DAOS_PROP_PO_SVC_OPS_ENTRY_AGE, + /** PEM intermediate CA bundle for per-pool node auth, default empty */ + DAOS_PROP_PO_POOL_CA, + /** Per-CN cert revocation watermarks: opaque JSON blob managed by the + * control plane; engine stores and ships verbatim. Default empty. + */ + DAOS_PROP_PO_CERT_WATERMARKS, DAOS_PROP_PO_MAX, }; @@ -153,6 +159,9 @@ struct daos_prop_byteval { size_t dpb_len; }; +/** Hard cap on a byteval prop's wire/memory length; bounds decode-time allocation. */ +#define DAOS_PROP_BYTEVAL_MAX_LEN (1U << 20) + #define DAOS_PROP_PO_EC_CELL_SZ_MIN (1UL << 10) #define DAOS_PROP_PO_EC_CELL_SZ_MAX (1UL << 30) @@ -871,6 +880,16 @@ int daos_prop_entry_cmp_acl(struct daos_prop_entry *entry1, struct daos_prop_entry *entry2); +/** + * Compare a pair of byteval-typed daos_prop_entry. Both must satisfy + * daos_prop_has_byteval(); empty (NULL or zero-length) values match. + * + * \return 0 Entries match + * -DER_MISMATCH Entries do NOT match + */ +int +daos_prop_entry_cmp_byteval(struct daos_prop_entry *entry1, struct daos_prop_entry *entry2); + /** * Duplicate container roots from one DAOS prop entry to another. * Convenience function. diff --git a/src/include/daos_srv/daos_engine.h b/src/include/daos_srv/daos_engine.h index c32b580db47..b5b025ade9f 100644 --- a/src/include/daos_srv/daos_engine.h +++ b/src/include/daos_srv/daos_engine.h @@ -398,14 +398,14 @@ struct dss_module { int (*sm_setup)(void); /* Cleanup function, invoked before stopping progressing */ int (*sm_cleanup)(void); - /* Number of RPC protocols this module supports - max 2 */ + /* Number of RPC protocols this module supports - max 3 */ int sm_proto_count; /* Array of whole list of RPC definition for request sent by nodes */ - struct crt_proto_format *sm_proto_fmt[2]; + struct crt_proto_format *sm_proto_fmt[3]; /* Array of the count of RPCs which are dedicated for client nodes only */ - uint32_t sm_cli_count[2]; + uint32_t sm_cli_count[3]; /* Array of RPC handler of these RPC, last entry of the array must be empty */ - struct daos_rpc_handler *sm_handlers[2]; + struct daos_rpc_handler *sm_handlers[3]; /* dRPC handlers, for unix socket comm, last entry must be empty */ struct dss_drpc_handler *sm_drpc_handlers; diff --git a/src/include/daos_srv/security.h b/src/include/daos_srv/security.h index 28fe83852b3..0382d236f2e 100644 --- a/src/include/daos_srv/security.h +++ b/src/include/daos_srv/security.h @@ -1,5 +1,6 @@ /* * (C) Copyright 2019-2024 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -349,4 +350,27 @@ ds_sec_get_admin_cont_capabilities(void); int ds_sec_creds_are_same_user(d_iov_t *cred_x, d_iov_t *cred_y); +/** + * Validate a per-pool node certificate and proof-of-possession against the + * pool's CA bundle and per-CN revocation watermarks via control-plane dRPC. + * + * \param[in] pool_uuid Pool UUID + * \param[in] pool_ca PEM-encoded pool intermediate CA bundle (required) + * \param[in] machine Credential machine name for CN cross-check (may be NULL) + * \param[in] cert_watermarks Per-CN revocation watermarks (may be NULL) + * \param[in] node_cert PEM-encoded node certificate (NULL/empty → -DER_NO_CERT) + * \param[in] node_cert_pop PoP signature (required) + * \param[in] node_cert_payload Signed PoP payload (required) + * + * \return 0 Success + * -DER_NO_CERT No node certificate presented + * -DER_BAD_CERT Chain validation failed or cert revoked + * -DER_NO_PERM PoP verification failed + * -DER_* Other dRPC transport or unmarshal errors + */ +int +ds_sec_validate_node_cert(uuid_t pool_uuid, d_iov_t *pool_ca, const char *machine, + d_iov_t *cert_watermarks, d_iov_t *node_cert, d_iov_t *node_cert_pop, + d_iov_t *node_cert_payload); + #endif /* __DAOS_SRV_SECURITY_H__ */ diff --git a/src/mgmt/pool.pb-c.c b/src/mgmt/pool.pb-c.c index 929df01b990..8c1f63d11e1 100644 --- a/src/mgmt/pool.pb-c.c +++ b/src/mgmt/pool.pb-c.c @@ -1594,258 +1594,1388 @@ void mgmt__pool_self_heal_eval_req__free_unpacked assert(message->base.descriptor == &mgmt__pool_self_heal_eval_req__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void mgmt__pool_get_careq__init + (Mgmt__PoolGetCAReq *message) +{ + static const Mgmt__PoolGetCAReq init_value = MGMT__POOL_GET_CAREQ__INIT; + *message = init_value; +} +size_t mgmt__pool_get_careq__get_packed_size + (const Mgmt__PoolGetCAReq *message) +{ + assert(message->base.descriptor == &mgmt__pool_get_careq__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_get_careq__pack + (const Mgmt__PoolGetCAReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_get_careq__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_get_careq__pack_to_buffer + (const Mgmt__PoolGetCAReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_get_careq__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolGetCAReq * + mgmt__pool_get_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolGetCAReq *) + protobuf_c_message_unpack (&mgmt__pool_get_careq__descriptor, + allocator, len, data); +} +void mgmt__pool_get_careq__free_unpacked + (Mgmt__PoolGetCAReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_get_careq__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_get_caresp__init + (Mgmt__PoolGetCAResp *message) +{ + static const Mgmt__PoolGetCAResp init_value = MGMT__POOL_GET_CARESP__INIT; + *message = init_value; +} +size_t mgmt__pool_get_caresp__get_packed_size + (const Mgmt__PoolGetCAResp *message) +{ + assert(message->base.descriptor == &mgmt__pool_get_caresp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_get_caresp__pack + (const Mgmt__PoolGetCAResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_get_caresp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_get_caresp__pack_to_buffer + (const Mgmt__PoolGetCAResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_get_caresp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolGetCAResp * + mgmt__pool_get_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolGetCAResp *) + protobuf_c_message_unpack (&mgmt__pool_get_caresp__descriptor, + allocator, len, data); +} +void mgmt__pool_get_caresp__free_unpacked + (Mgmt__PoolGetCAResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_get_caresp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_add_careq__init + (Mgmt__PoolAddCAReq *message) +{ + static const Mgmt__PoolAddCAReq init_value = MGMT__POOL_ADD_CAREQ__INIT; + *message = init_value; +} +size_t mgmt__pool_add_careq__get_packed_size + (const Mgmt__PoolAddCAReq *message) +{ + assert(message->base.descriptor == &mgmt__pool_add_careq__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_add_careq__pack + (const Mgmt__PoolAddCAReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_add_careq__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_add_careq__pack_to_buffer + (const Mgmt__PoolAddCAReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_add_careq__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolAddCAReq * + mgmt__pool_add_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolAddCAReq *) + protobuf_c_message_unpack (&mgmt__pool_add_careq__descriptor, + allocator, len, data); +} +void mgmt__pool_add_careq__free_unpacked + (Mgmt__PoolAddCAReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_add_careq__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_add_caresp__init + (Mgmt__PoolAddCAResp *message) +{ + static const Mgmt__PoolAddCAResp init_value = MGMT__POOL_ADD_CARESP__INIT; + *message = init_value; +} +size_t mgmt__pool_add_caresp__get_packed_size + (const Mgmt__PoolAddCAResp *message) +{ + assert(message->base.descriptor == &mgmt__pool_add_caresp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_add_caresp__pack + (const Mgmt__PoolAddCAResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_add_caresp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_add_caresp__pack_to_buffer + (const Mgmt__PoolAddCAResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_add_caresp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolAddCAResp * + mgmt__pool_add_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolAddCAResp *) + protobuf_c_message_unpack (&mgmt__pool_add_caresp__descriptor, + allocator, len, data); +} +void mgmt__pool_add_caresp__free_unpacked + (Mgmt__PoolAddCAResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_add_caresp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_remove_careq__init + (Mgmt__PoolRemoveCAReq *message) +{ + static const Mgmt__PoolRemoveCAReq init_value = MGMT__POOL_REMOVE_CAREQ__INIT; + *message = init_value; +} +size_t mgmt__pool_remove_careq__get_packed_size + (const Mgmt__PoolRemoveCAReq *message) +{ + assert(message->base.descriptor == &mgmt__pool_remove_careq__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_remove_careq__pack + (const Mgmt__PoolRemoveCAReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_remove_careq__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_remove_careq__pack_to_buffer + (const Mgmt__PoolRemoveCAReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_remove_careq__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolRemoveCAReq * + mgmt__pool_remove_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolRemoveCAReq *) + protobuf_c_message_unpack (&mgmt__pool_remove_careq__descriptor, + allocator, len, data); +} +void mgmt__pool_remove_careq__free_unpacked + (Mgmt__PoolRemoveCAReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_remove_careq__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_remove_caresp__init + (Mgmt__PoolRemoveCAResp *message) +{ + static const Mgmt__PoolRemoveCAResp init_value = MGMT__POOL_REMOVE_CARESP__INIT; + *message = init_value; +} +size_t mgmt__pool_remove_caresp__get_packed_size + (const Mgmt__PoolRemoveCAResp *message) +{ + assert(message->base.descriptor == &mgmt__pool_remove_caresp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_remove_caresp__pack + (const Mgmt__PoolRemoveCAResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_remove_caresp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_remove_caresp__pack_to_buffer + (const Mgmt__PoolRemoveCAResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_remove_caresp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolRemoveCAResp * + mgmt__pool_remove_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolRemoveCAResp *) + protobuf_c_message_unpack (&mgmt__pool_remove_caresp__descriptor, + allocator, len, data); +} +void mgmt__pool_remove_caresp__free_unpacked + (Mgmt__PoolRemoveCAResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_remove_caresp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_get_cert_watermarks_req__init + (Mgmt__PoolGetCertWatermarksReq *message) +{ + static const Mgmt__PoolGetCertWatermarksReq init_value = MGMT__POOL_GET_CERT_WATERMARKS_REQ__INIT; + *message = init_value; +} +size_t mgmt__pool_get_cert_watermarks_req__get_packed_size + (const Mgmt__PoolGetCertWatermarksReq *message) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_req__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_get_cert_watermarks_req__pack + (const Mgmt__PoolGetCertWatermarksReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_req__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_get_cert_watermarks_req__pack_to_buffer + (const Mgmt__PoolGetCertWatermarksReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_req__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolGetCertWatermarksReq * + mgmt__pool_get_cert_watermarks_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolGetCertWatermarksReq *) + protobuf_c_message_unpack (&mgmt__pool_get_cert_watermarks_req__descriptor, + allocator, len, data); +} +void mgmt__pool_get_cert_watermarks_req__free_unpacked + (Mgmt__PoolGetCertWatermarksReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_req__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_get_cert_watermarks_resp__init + (Mgmt__PoolGetCertWatermarksResp *message) +{ + static const Mgmt__PoolGetCertWatermarksResp init_value = MGMT__POOL_GET_CERT_WATERMARKS_RESP__INIT; + *message = init_value; +} +size_t mgmt__pool_get_cert_watermarks_resp__get_packed_size + (const Mgmt__PoolGetCertWatermarksResp *message) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_resp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_get_cert_watermarks_resp__pack + (const Mgmt__PoolGetCertWatermarksResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_resp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_get_cert_watermarks_resp__pack_to_buffer + (const Mgmt__PoolGetCertWatermarksResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_resp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolGetCertWatermarksResp * + mgmt__pool_get_cert_watermarks_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolGetCertWatermarksResp *) + protobuf_c_message_unpack (&mgmt__pool_get_cert_watermarks_resp__descriptor, + allocator, len, data); +} +void mgmt__pool_get_cert_watermarks_resp__free_unpacked + (Mgmt__PoolGetCertWatermarksResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_get_cert_watermarks_resp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_revoke_client_req__init + (Mgmt__PoolRevokeClientReq *message) +{ + static const Mgmt__PoolRevokeClientReq init_value = MGMT__POOL_REVOKE_CLIENT_REQ__INIT; + *message = init_value; +} +size_t mgmt__pool_revoke_client_req__get_packed_size + (const Mgmt__PoolRevokeClientReq *message) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_req__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_revoke_client_req__pack + (const Mgmt__PoolRevokeClientReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_req__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_revoke_client_req__pack_to_buffer + (const Mgmt__PoolRevokeClientReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_req__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolRevokeClientReq * + mgmt__pool_revoke_client_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolRevokeClientReq *) + protobuf_c_message_unpack (&mgmt__pool_revoke_client_req__descriptor, + allocator, len, data); +} +void mgmt__pool_revoke_client_req__free_unpacked + (Mgmt__PoolRevokeClientReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_revoke_client_req__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void mgmt__pool_revoke_client_resp__init + (Mgmt__PoolRevokeClientResp *message) +{ + static const Mgmt__PoolRevokeClientResp init_value = MGMT__POOL_REVOKE_CLIENT_RESP__INIT; + *message = init_value; +} +size_t mgmt__pool_revoke_client_resp__get_packed_size + (const Mgmt__PoolRevokeClientResp *message) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_resp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t mgmt__pool_revoke_client_resp__pack + (const Mgmt__PoolRevokeClientResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_resp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t mgmt__pool_revoke_client_resp__pack_to_buffer + (const Mgmt__PoolRevokeClientResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &mgmt__pool_revoke_client_resp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Mgmt__PoolRevokeClientResp * + mgmt__pool_revoke_client_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Mgmt__PoolRevokeClientResp *) + protobuf_c_message_unpack (&mgmt__pool_revoke_client_resp__descriptor, + allocator, len, data); +} +void mgmt__pool_revoke_client_resp__free_unpacked + (Mgmt__PoolRevokeClientResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &mgmt__pool_revoke_client_resp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} static const ProtobufCFieldDescriptor mgmt__pool_create_req__field_descriptors[14] = { { - "uuid", + "uuid", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, uuid), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sys", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, sys), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "user", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, user), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "user_group", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, user_group), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "acl", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_STRING, + offsetof(Mgmt__PoolCreateReq, n_acl), + offsetof(Mgmt__PoolCreateReq, acl), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "properties", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolCreateReq, n_properties), + offsetof(Mgmt__PoolCreateReq, properties), + &mgmt__pool_property__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "fault_domains", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolCreateReq, n_fault_domains), + offsetof(Mgmt__PoolCreateReq, fault_domains), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "num_svc_reps", + 8, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, num_svc_reps), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "total_bytes", + 9, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, total_bytes), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tier_ratio", + 10, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Mgmt__PoolCreateReq, n_tier_ratio), + offsetof(Mgmt__PoolCreateReq, tier_ratio), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "num_ranks", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, num_ranks), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ranks", + 12, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolCreateReq, n_ranks), + offsetof(Mgmt__PoolCreateReq, ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tier_bytes", + 13, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT64, + offsetof(Mgmt__PoolCreateReq, n_tier_bytes), + offsetof(Mgmt__PoolCreateReq, tier_bytes), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mem_ratio", + 14, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_FLOAT, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateReq, mem_ratio), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_create_req__field_indices_by_name[] = { + 4, /* field[4] = acl */ + 6, /* field[6] = fault_domains */ + 13, /* field[13] = mem_ratio */ + 10, /* field[10] = num_ranks */ + 7, /* field[7] = num_svc_reps */ + 5, /* field[5] = properties */ + 11, /* field[11] = ranks */ + 1, /* field[1] = sys */ + 12, /* field[12] = tier_bytes */ + 9, /* field[9] = tier_ratio */ + 8, /* field[8] = total_bytes */ + 2, /* field[2] = user */ + 3, /* field[3] = user_group */ + 0, /* field[0] = uuid */ +}; +static const ProtobufCIntRange mgmt__pool_create_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 14 } +}; +const ProtobufCMessageDescriptor mgmt__pool_create_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolCreateReq", + "PoolCreateReq", + "Mgmt__PoolCreateReq", + "mgmt", + sizeof(Mgmt__PoolCreateReq), + 14, + mgmt__pool_create_req__field_descriptors, + mgmt__pool_create_req__field_indices_by_name, + 1, mgmt__pool_create_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_create_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_create_resp__field_descriptors[7] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateResp, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "svc_ldr", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateResp, svc_ldr), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "svc_reps", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolCreateResp, n_svc_reps), + offsetof(Mgmt__PoolCreateResp, svc_reps), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tgt_ranks", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolCreateResp, n_tgt_ranks), + offsetof(Mgmt__PoolCreateResp, tgt_ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tier_bytes", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT64, + offsetof(Mgmt__PoolCreateResp, n_tier_bytes), + offsetof(Mgmt__PoolCreateResp, tier_bytes), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mem_file_bytes", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateResp, mem_file_bytes), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "md_on_ssd_active", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolCreateResp, md_on_ssd_active), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_create_resp__field_indices_by_name[] = { + 6, /* field[6] = md_on_ssd_active */ + 5, /* field[5] = mem_file_bytes */ + 0, /* field[0] = status */ + 1, /* field[1] = svc_ldr */ + 2, /* field[2] = svc_reps */ + 3, /* field[3] = tgt_ranks */ + 4, /* field[4] = tier_bytes */ +}; +static const ProtobufCIntRange mgmt__pool_create_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor mgmt__pool_create_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolCreateResp", + "PoolCreateResp", + "Mgmt__PoolCreateResp", + "mgmt", + sizeof(Mgmt__PoolCreateResp), + 7, + mgmt__pool_create_resp__field_descriptors, + mgmt__pool_create_resp__field_indices_by_name, + 1, mgmt__pool_create_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_create_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_destroy_req__field_descriptors[5] = +{ + { + "sys", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDestroyReq, sys), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "id", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDestroyReq, id), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "force", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDestroyReq, force), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "svc_ranks", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolDestroyReq, n_svc_ranks), + offsetof(Mgmt__PoolDestroyReq, svc_ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "recursive", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDestroyReq, recursive), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_destroy_req__field_indices_by_name[] = { + 2, /* field[2] = force */ + 1, /* field[1] = id */ + 4, /* field[4] = recursive */ + 3, /* field[3] = svc_ranks */ + 0, /* field[0] = sys */ +}; +static const ProtobufCIntRange mgmt__pool_destroy_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor mgmt__pool_destroy_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolDestroyReq", + "PoolDestroyReq", + "Mgmt__PoolDestroyReq", + "mgmt", + sizeof(Mgmt__PoolDestroyReq), + 5, + mgmt__pool_destroy_req__field_descriptors, + mgmt__pool_destroy_req__field_indices_by_name, + 1, mgmt__pool_destroy_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_destroy_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_destroy_resp__field_descriptors[1] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDestroyResp, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_destroy_resp__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__pool_destroy_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor mgmt__pool_destroy_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolDestroyResp", + "PoolDestroyResp", + "Mgmt__PoolDestroyResp", + "mgmt", + sizeof(Mgmt__PoolDestroyResp), + 1, + mgmt__pool_destroy_resp__field_descriptors, + mgmt__pool_destroy_resp__field_indices_by_name, + 1, mgmt__pool_destroy_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_destroy_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_evict_req__field_descriptors[7] = +{ + { + "sys", 1, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, uuid), + offsetof(Mgmt__PoolEvictReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "sys", + "id", 2, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, sys), + offsetof(Mgmt__PoolEvictReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "user", + "svc_ranks", 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolEvictReq, n_svc_ranks), + offsetof(Mgmt__PoolEvictReq, svc_ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "handles", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_STRING, + offsetof(Mgmt__PoolEvictReq, n_handles), + offsetof(Mgmt__PoolEvictReq, handles), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "destroy", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolEvictReq, destroy), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "force_destroy", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolEvictReq, force_destroy), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "machine", + 7, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, user), + offsetof(Mgmt__PoolEvictReq, machine), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_evict_req__field_indices_by_name[] = { + 4, /* field[4] = destroy */ + 5, /* field[5] = force_destroy */ + 3, /* field[3] = handles */ + 1, /* field[1] = id */ + 6, /* field[6] = machine */ + 2, /* field[2] = svc_ranks */ + 0, /* field[0] = sys */ +}; +static const ProtobufCIntRange mgmt__pool_evict_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor mgmt__pool_evict_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolEvictReq", + "PoolEvictReq", + "Mgmt__PoolEvictReq", + "mgmt", + sizeof(Mgmt__PoolEvictReq), + 7, + mgmt__pool_evict_req__field_descriptors, + mgmt__pool_evict_req__field_indices_by_name, + 1, mgmt__pool_evict_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_evict_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_evict_resp__field_descriptors[2] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolEvictResp, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { - "user_group", - 4, + "count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolEvictResp, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_evict_resp__field_indices_by_name[] = { + 1, /* field[1] = count */ + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__pool_evict_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor mgmt__pool_evict_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolEvictResp", + "PoolEvictResp", + "Mgmt__PoolEvictResp", + "mgmt", + sizeof(Mgmt__PoolEvictResp), + 2, + mgmt__pool_evict_resp__field_descriptors, + mgmt__pool_evict_resp__field_indices_by_name, + 1, mgmt__pool_evict_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_evict_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_exclude_req__field_descriptors[6] = +{ + { + "sys", + 1, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, user_group), + offsetof(Mgmt__PoolExcludeReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "acl", - 5, - PROTOBUF_C_LABEL_REPEATED, + "id", + 2, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, - offsetof(Mgmt__PoolCreateReq, n_acl), - offsetof(Mgmt__PoolCreateReq, acl), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolExcludeReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "properties", - 6, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolCreateReq, n_properties), - offsetof(Mgmt__PoolCreateReq, properties), - &mgmt__pool_property__descriptor, + "rank", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolExcludeReq, rank), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "fault_domains", - 7, + "target_idx", + 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolCreateReq, n_fault_domains), - offsetof(Mgmt__PoolCreateReq, fault_domains), + offsetof(Mgmt__PoolExcludeReq, n_target_idx), + offsetof(Mgmt__PoolExcludeReq, target_idx), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "svc_ranks", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolExcludeReq, n_svc_ranks), + offsetof(Mgmt__PoolExcludeReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "num_svc_reps", - 8, + "force", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolExcludeReq, force), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_exclude_req__field_indices_by_name[] = { + 5, /* field[5] = force */ + 1, /* field[1] = id */ + 2, /* field[2] = rank */ + 4, /* field[4] = svc_ranks */ + 0, /* field[0] = sys */ + 3, /* field[3] = target_idx */ +}; +static const ProtobufCIntRange mgmt__pool_exclude_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 6 } +}; +const ProtobufCMessageDescriptor mgmt__pool_exclude_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolExcludeReq", + "PoolExcludeReq", + "Mgmt__PoolExcludeReq", + "mgmt", + sizeof(Mgmt__PoolExcludeReq), + 6, + mgmt__pool_exclude_req__field_descriptors, + mgmt__pool_exclude_req__field_indices_by_name, + 1, mgmt__pool_exclude_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_exclude_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_exclude_resp__field_descriptors[1] = +{ + { + "status", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, num_svc_reps), + offsetof(Mgmt__PoolExcludeResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_exclude_resp__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__pool_exclude_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor mgmt__pool_exclude_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolExcludeResp", + "PoolExcludeResp", + "Mgmt__PoolExcludeResp", + "mgmt", + sizeof(Mgmt__PoolExcludeResp), + 1, + mgmt__pool_exclude_resp__field_descriptors, + mgmt__pool_exclude_resp__field_indices_by_name, + 1, mgmt__pool_exclude_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_exclude_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_drain_req__field_descriptors[5] = +{ { - "total_bytes", - 9, + "sys", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, total_bytes), - NULL, + offsetof(Mgmt__PoolDrainReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tier_ratio", - 10, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_DOUBLE, - offsetof(Mgmt__PoolCreateReq, n_tier_ratio), - offsetof(Mgmt__PoolCreateReq, tier_ratio), - NULL, + "id", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolDrainReq, id), NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + &protobuf_c_empty_string, + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "num_ranks", - 11, + "rank", + 3, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, num_ranks), + offsetof(Mgmt__PoolDrainReq, rank), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "ranks", - 12, + "target_idx", + 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolCreateReq, n_ranks), - offsetof(Mgmt__PoolCreateReq, ranks), + offsetof(Mgmt__PoolDrainReq, n_target_idx), + offsetof(Mgmt__PoolDrainReq, target_idx), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tier_bytes", - 13, + "svc_ranks", + 5, PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolCreateReq, n_tier_bytes), - offsetof(Mgmt__PoolCreateReq, tier_bytes), + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolDrainReq, n_svc_ranks), + offsetof(Mgmt__PoolDrainReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_drain_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = rank */ + 4, /* field[4] = svc_ranks */ + 0, /* field[0] = sys */ + 3, /* field[3] = target_idx */ +}; +static const ProtobufCIntRange mgmt__pool_drain_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor mgmt__pool_drain_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolDrainReq", + "PoolDrainReq", + "Mgmt__PoolDrainReq", + "mgmt", + sizeof(Mgmt__PoolDrainReq), + 5, + mgmt__pool_drain_req__field_descriptors, + mgmt__pool_drain_req__field_indices_by_name, + 1, mgmt__pool_drain_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_drain_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_drain_resp__field_descriptors[1] = +{ { - "mem_ratio", - 14, + "status", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_FLOAT, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateReq, mem_ratio), + offsetof(Mgmt__PoolDrainResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_create_req__field_indices_by_name[] = { - 4, /* field[4] = acl */ - 6, /* field[6] = fault_domains */ - 13, /* field[13] = mem_ratio */ - 10, /* field[10] = num_ranks */ - 7, /* field[7] = num_svc_reps */ - 5, /* field[5] = properties */ - 11, /* field[11] = ranks */ - 1, /* field[1] = sys */ - 12, /* field[12] = tier_bytes */ - 9, /* field[9] = tier_ratio */ - 8, /* field[8] = total_bytes */ - 2, /* field[2] = user */ - 3, /* field[3] = user_group */ - 0, /* field[0] = uuid */ +static const unsigned mgmt__pool_drain_resp__field_indices_by_name[] = { + 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__pool_create_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_drain_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 14 } + { 0, 1 } }; -const ProtobufCMessageDescriptor mgmt__pool_create_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_drain_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolCreateReq", - "PoolCreateReq", - "Mgmt__PoolCreateReq", + "mgmt.PoolDrainResp", + "PoolDrainResp", + "Mgmt__PoolDrainResp", "mgmt", - sizeof(Mgmt__PoolCreateReq), - 14, - mgmt__pool_create_req__field_descriptors, - mgmt__pool_create_req__field_indices_by_name, - 1, mgmt__pool_create_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_create_req__init, + sizeof(Mgmt__PoolDrainResp), + 1, + mgmt__pool_drain_resp__field_descriptors, + mgmt__pool_drain_resp__field_indices_by_name, + 1, mgmt__pool_drain_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_drain_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_create_resp__field_descriptors[7] = +static const ProtobufCFieldDescriptor mgmt__pool_extend_req__field_descriptors[7] = { { - "status", + "sys", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateResp, status), - NULL, + offsetof(Mgmt__PoolExtendReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ldr", + "id", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateResp, svc_ldr), - NULL, + offsetof(Mgmt__PoolExtendReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_reps", + "ranks", 3, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolCreateResp, n_svc_reps), - offsetof(Mgmt__PoolCreateResp, svc_reps), + offsetof(Mgmt__PoolExtendReq, n_ranks), + offsetof(Mgmt__PoolExtendReq, ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tgt_ranks", + "svc_ranks", 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolCreateResp, n_tgt_ranks), - offsetof(Mgmt__PoolCreateResp, tgt_ranks), + offsetof(Mgmt__PoolExtendReq, n_svc_ranks), + offsetof(Mgmt__PoolExtendReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ @@ -1856,68 +2986,119 @@ static const ProtobufCFieldDescriptor mgmt__pool_create_resp__field_descriptors[ 5, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolCreateResp, n_tier_bytes), - offsetof(Mgmt__PoolCreateResp, tier_bytes), + offsetof(Mgmt__PoolExtendReq, n_tier_bytes), + offsetof(Mgmt__PoolExtendReq, tier_bytes), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mem_file_bytes", + "fault_domains", 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolExtendReq, n_fault_domains), + offsetof(Mgmt__PoolExtendReq, fault_domains), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mem_ratio", + 7, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_FLOAT, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateResp, mem_file_bytes), + offsetof(Mgmt__PoolExtendReq, mem_ratio), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_extend_req__field_indices_by_name[] = { + 5, /* field[5] = fault_domains */ + 1, /* field[1] = id */ + 6, /* field[6] = mem_ratio */ + 2, /* field[2] = ranks */ + 3, /* field[3] = svc_ranks */ + 0, /* field[0] = sys */ + 4, /* field[4] = tier_bytes */ +}; +static const ProtobufCIntRange mgmt__pool_extend_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor mgmt__pool_extend_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolExtendReq", + "PoolExtendReq", + "Mgmt__PoolExtendReq", + "mgmt", + sizeof(Mgmt__PoolExtendReq), + 7, + mgmt__pool_extend_req__field_descriptors, + mgmt__pool_extend_req__field_indices_by_name, + 1, mgmt__pool_extend_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_extend_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_extend_resp__field_descriptors[2] = +{ { - "md_on_ssd_active", - 7, + "status", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolCreateResp, md_on_ssd_active), + offsetof(Mgmt__PoolExtendResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "tier_bytes", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT64, + offsetof(Mgmt__PoolExtendResp, n_tier_bytes), + offsetof(Mgmt__PoolExtendResp, tier_bytes), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; -static const unsigned mgmt__pool_create_resp__field_indices_by_name[] = { - 6, /* field[6] = md_on_ssd_active */ - 5, /* field[5] = mem_file_bytes */ +static const unsigned mgmt__pool_extend_resp__field_indices_by_name[] = { 0, /* field[0] = status */ - 1, /* field[1] = svc_ldr */ - 2, /* field[2] = svc_reps */ - 3, /* field[3] = tgt_ranks */ - 4, /* field[4] = tier_bytes */ + 1, /* field[1] = tier_bytes */ }; -static const ProtobufCIntRange mgmt__pool_create_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_extend_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 7 } + { 0, 2 } }; -const ProtobufCMessageDescriptor mgmt__pool_create_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_extend_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolCreateResp", - "PoolCreateResp", - "Mgmt__PoolCreateResp", + "mgmt.PoolExtendResp", + "PoolExtendResp", + "Mgmt__PoolExtendResp", "mgmt", - sizeof(Mgmt__PoolCreateResp), - 7, - mgmt__pool_create_resp__field_descriptors, - mgmt__pool_create_resp__field_indices_by_name, - 1, mgmt__pool_create_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_create_resp__init, + sizeof(Mgmt__PoolExtendResp), + 2, + mgmt__pool_extend_resp__field_descriptors, + mgmt__pool_extend_resp__field_indices_by_name, + 1, mgmt__pool_extend_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_extend_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_destroy_req__field_descriptors[5] = +static const ProtobufCFieldDescriptor mgmt__pool_reint_req__field_descriptors[7] = { { "sys", @@ -1925,7 +3106,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_destroy_req__field_descriptors[ PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDestroyReq, sys), + offsetof(Mgmt__PoolReintReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -1937,77 +3118,103 @@ static const ProtobufCFieldDescriptor mgmt__pool_destroy_req__field_descriptors[ PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDestroyReq, id), + offsetof(Mgmt__PoolReintReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "force", + "rank", 3, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDestroyReq, force), + offsetof(Mgmt__PoolReintReq, rank), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "target_idx", 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolDestroyReq, n_svc_ranks), - offsetof(Mgmt__PoolDestroyReq, svc_ranks), + offsetof(Mgmt__PoolReintReq, n_target_idx), + offsetof(Mgmt__PoolReintReq, target_idx), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "recursive", + "svc_ranks", 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolReintReq, n_svc_ranks), + offsetof(Mgmt__PoolReintReq, svc_ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tier_bytes", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT64, + offsetof(Mgmt__PoolReintReq, n_tier_bytes), + offsetof(Mgmt__PoolReintReq, tier_bytes), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mem_ratio", + 7, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, + PROTOBUF_C_TYPE_FLOAT, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDestroyReq, recursive), + offsetof(Mgmt__PoolReintReq, mem_ratio), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_destroy_req__field_indices_by_name[] = { - 2, /* field[2] = force */ +static const unsigned mgmt__pool_reint_req__field_indices_by_name[] = { 1, /* field[1] = id */ - 4, /* field[4] = recursive */ - 3, /* field[3] = svc_ranks */ + 6, /* field[6] = mem_ratio */ + 2, /* field[2] = rank */ + 4, /* field[4] = svc_ranks */ 0, /* field[0] = sys */ + 3, /* field[3] = target_idx */ + 5, /* field[5] = tier_bytes */ }; -static const ProtobufCIntRange mgmt__pool_destroy_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_reint_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 5 } + { 0, 7 } }; -const ProtobufCMessageDescriptor mgmt__pool_destroy_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_reint_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolDestroyReq", - "PoolDestroyReq", - "Mgmt__PoolDestroyReq", + "mgmt.PoolReintReq", + "PoolReintReq", + "Mgmt__PoolReintReq", "mgmt", - sizeof(Mgmt__PoolDestroyReq), - 5, - mgmt__pool_destroy_req__field_descriptors, - mgmt__pool_destroy_req__field_indices_by_name, - 1, mgmt__pool_destroy_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_destroy_req__init, + sizeof(Mgmt__PoolReintReq), + 7, + mgmt__pool_reint_req__field_descriptors, + mgmt__pool_reint_req__field_indices_by_name, + 1, mgmt__pool_reint_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_reint_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_destroy_resp__field_descriptors[1] = +static const ProtobufCFieldDescriptor mgmt__pool_reint_resp__field_descriptors[1] = { { "status", @@ -2015,37 +3222,37 @@ static const ProtobufCFieldDescriptor mgmt__pool_destroy_resp__field_descriptors PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDestroyResp, status), + offsetof(Mgmt__PoolReintResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_destroy_resp__field_indices_by_name[] = { +static const unsigned mgmt__pool_reint_resp__field_indices_by_name[] = { 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__pool_destroy_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_reint_resp__number_ranges[1 + 1] = { { 1, 0 }, { 0, 1 } }; -const ProtobufCMessageDescriptor mgmt__pool_destroy_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_reint_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolDestroyResp", - "PoolDestroyResp", - "Mgmt__PoolDestroyResp", + "mgmt.PoolReintResp", + "PoolReintResp", + "Mgmt__PoolReintResp", "mgmt", - sizeof(Mgmt__PoolDestroyResp), + sizeof(Mgmt__PoolReintResp), 1, - mgmt__pool_destroy_resp__field_descriptors, - mgmt__pool_destroy_resp__field_indices_by_name, - 1, mgmt__pool_destroy_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_destroy_resp__init, + mgmt__pool_reint_resp__field_descriptors, + mgmt__pool_reint_resp__field_indices_by_name, + 1, mgmt__pool_reint_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_reint_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_evict_req__field_descriptors[7] = +static const ProtobufCFieldDescriptor mgmt__list_pools_req__field_descriptors[1] = { { "sys", @@ -2053,115 +3260,127 @@ static const ProtobufCFieldDescriptor mgmt__pool_evict_req__field_descriptors[7] PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictReq, sys), + offsetof(Mgmt__ListPoolsReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__list_pools_req__field_indices_by_name[] = { + 0, /* field[0] = sys */ +}; +static const ProtobufCIntRange mgmt__list_pools_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor mgmt__list_pools_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.ListPoolsReq", + "ListPoolsReq", + "Mgmt__ListPoolsReq", + "mgmt", + sizeof(Mgmt__ListPoolsReq), + 1, + mgmt__list_pools_req__field_descriptors, + mgmt__list_pools_req__field_indices_by_name, + 1, mgmt__list_pools_req__number_ranges, + (ProtobufCMessageInit) mgmt__list_pools_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__list_pools_resp__pool__field_descriptors[5] = +{ { - "id", - 2, + "uuid", + 1, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictReq, id), + offsetof(Mgmt__ListPoolsResp__Pool, uuid), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", - 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolEvictReq, n_svc_ranks), - offsetof(Mgmt__PoolEvictReq, svc_ranks), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "handles", - 4, - PROTOBUF_C_LABEL_REPEATED, + "label", + 2, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, - offsetof(Mgmt__PoolEvictReq, n_handles), - offsetof(Mgmt__PoolEvictReq, handles), + 0, /* quantifier_offset */ + offsetof(Mgmt__ListPoolsResp__Pool, label), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "destroy", - 5, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictReq, destroy), + "svc_reps", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__ListPoolsResp__Pool, n_svc_reps), + offsetof(Mgmt__ListPoolsResp__Pool, svc_reps), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "force_destroy", - 6, + "state", + 4, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictReq, force_destroy), - NULL, + offsetof(Mgmt__ListPoolsResp__Pool, state), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "machine", - 7, + "rebuild_state", + 5, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictReq, machine), + offsetof(Mgmt__ListPoolsResp__Pool, rebuild_state), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_evict_req__field_indices_by_name[] = { - 4, /* field[4] = destroy */ - 5, /* field[5] = force_destroy */ - 3, /* field[3] = handles */ - 1, /* field[1] = id */ - 6, /* field[6] = machine */ - 2, /* field[2] = svc_ranks */ - 0, /* field[0] = sys */ +static const unsigned mgmt__list_pools_resp__pool__field_indices_by_name[] = { + 1, /* field[1] = label */ + 4, /* field[4] = rebuild_state */ + 3, /* field[3] = state */ + 2, /* field[2] = svc_reps */ + 0, /* field[0] = uuid */ }; -static const ProtobufCIntRange mgmt__pool_evict_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__list_pools_resp__pool__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 7 } + { 0, 5 } }; -const ProtobufCMessageDescriptor mgmt__pool_evict_req__descriptor = +const ProtobufCMessageDescriptor mgmt__list_pools_resp__pool__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolEvictReq", - "PoolEvictReq", - "Mgmt__PoolEvictReq", + "mgmt.ListPoolsResp.Pool", + "Pool", + "Mgmt__ListPoolsResp__Pool", "mgmt", - sizeof(Mgmt__PoolEvictReq), - 7, - mgmt__pool_evict_req__field_descriptors, - mgmt__pool_evict_req__field_indices_by_name, - 1, mgmt__pool_evict_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_evict_req__init, + sizeof(Mgmt__ListPoolsResp__Pool), + 5, + mgmt__list_pools_resp__pool__field_descriptors, + mgmt__list_pools_resp__pool__field_indices_by_name, + 1, mgmt__list_pools_resp__pool__number_ranges, + (ProtobufCMessageInit) mgmt__list_pools_resp__pool__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_evict_resp__field_descriptors[2] = +static const ProtobufCFieldDescriptor mgmt__list_pools_resp__field_descriptors[3] = { { "status", @@ -2169,50 +3388,63 @@ static const ProtobufCFieldDescriptor mgmt__pool_evict_resp__field_descriptors[2 PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictResp, status), + offsetof(Mgmt__ListPoolsResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "count", + "pools", 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__ListPoolsResp, n_pools), + offsetof(Mgmt__ListPoolsResp, pools), + &mgmt__list_pools_resp__pool__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "data_version", + 3, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolEvictResp, count), + offsetof(Mgmt__ListPoolsResp, data_version), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_evict_resp__field_indices_by_name[] = { - 1, /* field[1] = count */ +static const unsigned mgmt__list_pools_resp__field_indices_by_name[] = { + 2, /* field[2] = data_version */ + 1, /* field[1] = pools */ 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__pool_evict_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__list_pools_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_evict_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__list_pools_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolEvictResp", - "PoolEvictResp", - "Mgmt__PoolEvictResp", + "mgmt.ListPoolsResp", + "ListPoolsResp", + "Mgmt__ListPoolsResp", "mgmt", - sizeof(Mgmt__PoolEvictResp), - 2, - mgmt__pool_evict_resp__field_descriptors, - mgmt__pool_evict_resp__field_indices_by_name, - 1, mgmt__pool_evict_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_evict_resp__init, + sizeof(Mgmt__ListPoolsResp), + 3, + mgmt__list_pools_resp__field_descriptors, + mgmt__list_pools_resp__field_indices_by_name, + 1, mgmt__list_pools_resp__number_ranges, + (ProtobufCMessageInit) mgmt__list_pools_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_exclude_req__field_descriptors[6] = +static const ProtobufCFieldDescriptor mgmt__list_cont_req__field_descriptors[3] = { { "sys", @@ -2220,7 +3452,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_exclude_req__field_descriptors[ PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExcludeReq, sys), + offsetof(Mgmt__ListContReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -2232,1140 +3464,953 @@ static const ProtobufCFieldDescriptor mgmt__pool_exclude_req__field_descriptors[ PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExcludeReq, id), + offsetof(Mgmt__ListContReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "rank", - 3, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExcludeReq, rank), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "target_idx", - 4, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolExcludeReq, n_target_idx), - offsetof(Mgmt__PoolExcludeReq, target_idx), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, { "svc_ranks", - 5, + 3, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolExcludeReq, n_svc_ranks), - offsetof(Mgmt__PoolExcludeReq, svc_ranks), + offsetof(Mgmt__ListContReq, n_svc_ranks), + offsetof(Mgmt__ListContReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "force", - 6, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExcludeReq, force), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, }; -static const unsigned mgmt__pool_exclude_req__field_indices_by_name[] = { - 5, /* field[5] = force */ +static const unsigned mgmt__list_cont_req__field_indices_by_name[] = { 1, /* field[1] = id */ - 2, /* field[2] = rank */ - 4, /* field[4] = svc_ranks */ + 2, /* field[2] = svc_ranks */ 0, /* field[0] = sys */ - 3, /* field[3] = target_idx */ }; -static const ProtobufCIntRange mgmt__pool_exclude_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__list_cont_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 6 } + { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_exclude_req__descriptor = +const ProtobufCMessageDescriptor mgmt__list_cont_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolExcludeReq", - "PoolExcludeReq", - "Mgmt__PoolExcludeReq", + "mgmt.ListContReq", + "ListContReq", + "Mgmt__ListContReq", "mgmt", - sizeof(Mgmt__PoolExcludeReq), - 6, - mgmt__pool_exclude_req__field_descriptors, - mgmt__pool_exclude_req__field_indices_by_name, - 1, mgmt__pool_exclude_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_exclude_req__init, + sizeof(Mgmt__ListContReq), + 3, + mgmt__list_cont_req__field_descriptors, + mgmt__list_cont_req__field_indices_by_name, + 1, mgmt__list_cont_req__number_ranges, + (ProtobufCMessageInit) mgmt__list_cont_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_exclude_resp__field_descriptors[1] = +static const ProtobufCFieldDescriptor mgmt__list_cont_resp__cont__field_descriptors[1] = { { - "status", + "uuid", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExcludeResp, status), - NULL, + offsetof(Mgmt__ListContResp__Cont, uuid), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_exclude_resp__field_indices_by_name[] = { - 0, /* field[0] = status */ +static const unsigned mgmt__list_cont_resp__cont__field_indices_by_name[] = { + 0, /* field[0] = uuid */ }; -static const ProtobufCIntRange mgmt__pool_exclude_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__list_cont_resp__cont__number_ranges[1 + 1] = { { 1, 0 }, { 0, 1 } }; -const ProtobufCMessageDescriptor mgmt__pool_exclude_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__list_cont_resp__cont__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolExcludeResp", - "PoolExcludeResp", - "Mgmt__PoolExcludeResp", + "mgmt.ListContResp.Cont", + "Cont", + "Mgmt__ListContResp__Cont", "mgmt", - sizeof(Mgmt__PoolExcludeResp), + sizeof(Mgmt__ListContResp__Cont), 1, - mgmt__pool_exclude_resp__field_descriptors, - mgmt__pool_exclude_resp__field_indices_by_name, - 1, mgmt__pool_exclude_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_exclude_resp__init, + mgmt__list_cont_resp__cont__field_descriptors, + mgmt__list_cont_resp__cont__field_indices_by_name, + 1, mgmt__list_cont_resp__cont__number_ranges, + (ProtobufCMessageInit) mgmt__list_cont_resp__cont__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_drain_req__field_descriptors[5] = +static const ProtobufCFieldDescriptor mgmt__list_cont_resp__field_descriptors[2] = { { - "sys", + "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDrainReq, sys), + offsetof(Mgmt__ListContResp, status), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "containers", 2, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDrainReq, id), + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__ListContResp, n_containers), + offsetof(Mgmt__ListContResp, containers), + &mgmt__list_cont_resp__cont__descriptor, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__list_cont_resp__field_indices_by_name[] = { + 1, /* field[1] = containers */ + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__list_cont_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor mgmt__list_cont_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.ListContResp", + "ListContResp", + "Mgmt__ListContResp", + "mgmt", + sizeof(Mgmt__ListContResp), + 2, + mgmt__list_cont_resp__field_descriptors, + mgmt__list_cont_resp__field_indices_by_name, + 1, mgmt__list_cont_resp__number_ranges, + (ProtobufCMessageInit) mgmt__list_cont_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_query_req__field_descriptors[4] = +{ { - "rank", - 3, + "sys", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDrainReq, rank), - NULL, + offsetof(Mgmt__PoolQueryReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "target_idx", - 4, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolDrainReq, n_target_idx), - offsetof(Mgmt__PoolDrainReq, target_idx), - NULL, + "id", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryReq, id), NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + &protobuf_c_empty_string, + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { "svc_ranks", - 5, + 3, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolDrainReq, n_svc_ranks), - offsetof(Mgmt__PoolDrainReq, svc_ranks), + offsetof(Mgmt__PoolQueryReq, n_svc_ranks), + offsetof(Mgmt__PoolQueryReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__pool_drain_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 2, /* field[2] = rank */ - 4, /* field[4] = svc_ranks */ - 0, /* field[0] = sys */ - 3, /* field[3] = target_idx */ -}; -static const ProtobufCIntRange mgmt__pool_drain_req__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 5 } -}; -const ProtobufCMessageDescriptor mgmt__pool_drain_req__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolDrainReq", - "PoolDrainReq", - "Mgmt__PoolDrainReq", - "mgmt", - sizeof(Mgmt__PoolDrainReq), - 5, - mgmt__pool_drain_req__field_descriptors, - mgmt__pool_drain_req__field_indices_by_name, - 1, mgmt__pool_drain_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_drain_req__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__pool_drain_resp__field_descriptors[1] = -{ { - "status", - 1, + "query_mask", + 4, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolDrainResp, status), + offsetof(Mgmt__PoolQueryReq, query_mask), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_drain_resp__field_indices_by_name[] = { - 0, /* field[0] = status */ +static const unsigned mgmt__pool_query_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 3, /* field[3] = query_mask */ + 2, /* field[2] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_drain_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_query_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 1 } + { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__pool_drain_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_query_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolDrainResp", - "PoolDrainResp", - "Mgmt__PoolDrainResp", + "mgmt.PoolQueryReq", + "PoolQueryReq", + "Mgmt__PoolQueryReq", "mgmt", - sizeof(Mgmt__PoolDrainResp), - 1, - mgmt__pool_drain_resp__field_descriptors, - mgmt__pool_drain_resp__field_indices_by_name, - 1, mgmt__pool_drain_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_drain_resp__init, + sizeof(Mgmt__PoolQueryReq), + 4, + mgmt__pool_query_req__field_descriptors, + mgmt__pool_query_req__field_indices_by_name, + 1, mgmt__pool_query_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_query_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_extend_req__field_descriptors[7] = +static const ProtobufCFieldDescriptor mgmt__storage_usage_stats__field_descriptors[6] = { { - "sys", + "total", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExtendReq, sys), + offsetof(Mgmt__StorageUsageStats, total), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "free", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExtendReq, id), + offsetof(Mgmt__StorageUsageStats, free), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "ranks", + "min", 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolExtendReq, n_ranks), - offsetof(Mgmt__PoolExtendReq, ranks), + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Mgmt__StorageUsageStats, min), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "max", 4, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolExtendReq, n_svc_ranks), - offsetof(Mgmt__PoolExtendReq, svc_ranks), + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Mgmt__StorageUsageStats, max), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tier_bytes", + "mean", 5, - PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolExtendReq, n_tier_bytes), - offsetof(Mgmt__PoolExtendReq, tier_bytes), + 0, /* quantifier_offset */ + offsetof(Mgmt__StorageUsageStats, mean), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "fault_domains", + "media_type", 6, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolExtendReq, n_fault_domains), - offsetof(Mgmt__PoolExtendReq, fault_domains), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "mem_ratio", - 7, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_FLOAT, + PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExtendReq, mem_ratio), - NULL, + offsetof(Mgmt__StorageUsageStats, media_type), + &mgmt__storage_media_type__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_extend_req__field_indices_by_name[] = { - 5, /* field[5] = fault_domains */ - 1, /* field[1] = id */ - 6, /* field[6] = mem_ratio */ - 2, /* field[2] = ranks */ - 3, /* field[3] = svc_ranks */ - 0, /* field[0] = sys */ - 4, /* field[4] = tier_bytes */ +static const unsigned mgmt__storage_usage_stats__field_indices_by_name[] = { + 1, /* field[1] = free */ + 3, /* field[3] = max */ + 4, /* field[4] = mean */ + 5, /* field[5] = media_type */ + 2, /* field[2] = min */ + 0, /* field[0] = total */ }; -static const ProtobufCIntRange mgmt__pool_extend_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__storage_usage_stats__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 7 } + { 0, 6 } }; -const ProtobufCMessageDescriptor mgmt__pool_extend_req__descriptor = +const ProtobufCMessageDescriptor mgmt__storage_usage_stats__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolExtendReq", - "PoolExtendReq", - "Mgmt__PoolExtendReq", + "mgmt.StorageUsageStats", + "StorageUsageStats", + "Mgmt__StorageUsageStats", "mgmt", - sizeof(Mgmt__PoolExtendReq), - 7, - mgmt__pool_extend_req__field_descriptors, - mgmt__pool_extend_req__field_indices_by_name, - 1, mgmt__pool_extend_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_extend_req__init, + sizeof(Mgmt__StorageUsageStats), + 6, + mgmt__storage_usage_stats__field_descriptors, + mgmt__storage_usage_stats__field_indices_by_name, + 1, mgmt__storage_usage_stats__number_ranges, + (ProtobufCMessageInit) mgmt__storage_usage_stats__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_extend_resp__field_descriptors[2] = +static const ProtobufCEnumValue mgmt__pool_rebuild_status__state__enum_values_by_number[7] = +{ + { "BUSY", "MGMT__POOL_REBUILD_STATUS__STATE__BUSY", 0 }, + { "IDLE", "MGMT__POOL_REBUILD_STATUS__STATE__IDLE", 1 }, + { "DONE", "MGMT__POOL_REBUILD_STATUS__STATE__DONE", 2 }, + { "STOPPING", "MGMT__POOL_REBUILD_STATUS__STATE__STOPPING", 3 }, + { "STOPPED", "MGMT__POOL_REBUILD_STATUS__STATE__STOPPED", 4 }, + { "FAILING", "MGMT__POOL_REBUILD_STATUS__STATE__FAILING", 5 }, + { "FAILED", "MGMT__POOL_REBUILD_STATUS__STATE__FAILED", 6 }, +}; +static const ProtobufCIntRange mgmt__pool_rebuild_status__state__value_ranges[] = { +{0, 0},{0, 7} +}; +static const ProtobufCEnumValueIndex mgmt__pool_rebuild_status__state__enum_values_by_name[7] = +{ + { "BUSY", 0 }, + { "DONE", 2 }, + { "FAILED", 6 }, + { "FAILING", 5 }, + { "IDLE", 1 }, + { "STOPPED", 4 }, + { "STOPPING", 3 }, +}; +const ProtobufCEnumDescriptor mgmt__pool_rebuild_status__state__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "mgmt.PoolRebuildStatus.State", + "State", + "Mgmt__PoolRebuildStatus__State", + "mgmt", + 7, + mgmt__pool_rebuild_status__state__enum_values_by_number, + 7, + mgmt__pool_rebuild_status__state__enum_values_by_name, + 1, + mgmt__pool_rebuild_status__state__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_rebuild_status__field_descriptors[6] = { { "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStatus, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "state", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStatus, state), + &mgmt__pool_rebuild_status__state__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "objects", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolExtendResp, status), + offsetof(Mgmt__PoolRebuildStatus, objects), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tier_bytes", - 2, - PROTOBUF_C_LABEL_REPEATED, + "records", + 4, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolExtendResp, n_tier_bytes), - offsetof(Mgmt__PoolExtendResp, tier_bytes), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStatus, records), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "derived_state", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStatus, derived_state), + &mgmt__pool_rebuild_status__state__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "degraded", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStatus, degraded), + NULL, + NULL, + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_extend_resp__field_indices_by_name[] = { +static const unsigned mgmt__pool_rebuild_status__field_indices_by_name[] = { + 5, /* field[5] = degraded */ + 4, /* field[4] = derived_state */ + 2, /* field[2] = objects */ + 3, /* field[3] = records */ + 1, /* field[1] = state */ 0, /* field[0] = status */ - 1, /* field[1] = tier_bytes */ }; -static const ProtobufCIntRange mgmt__pool_extend_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_rebuild_status__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 6 } }; -const ProtobufCMessageDescriptor mgmt__pool_extend_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_rebuild_status__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolExtendResp", - "PoolExtendResp", - "Mgmt__PoolExtendResp", + "mgmt.PoolRebuildStatus", + "PoolRebuildStatus", + "Mgmt__PoolRebuildStatus", "mgmt", - sizeof(Mgmt__PoolExtendResp), - 2, - mgmt__pool_extend_resp__field_descriptors, - mgmt__pool_extend_resp__field_indices_by_name, - 1, mgmt__pool_extend_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_extend_resp__init, + sizeof(Mgmt__PoolRebuildStatus), + 6, + mgmt__pool_rebuild_status__field_descriptors, + mgmt__pool_rebuild_status__field_indices_by_name, + 1, mgmt__pool_rebuild_status__number_ranges, + (ProtobufCMessageInit) mgmt__pool_rebuild_status__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_reint_req__field_descriptors[7] = +static const ProtobufCFieldDescriptor mgmt__pool_query_resp__field_descriptors[24] = { { - "sys", + "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolReintReq, sys), + offsetof(Mgmt__PoolQueryResp, status), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "uuid", 2, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolReintReq, id), + offsetof(Mgmt__PoolQueryResp, uuid), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "rank", + "label", 3, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolReintReq, rank), - NULL, + offsetof(Mgmt__PoolQueryResp, label), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "target_idx", + "total_targets", 4, - PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolReintReq, n_target_idx), - offsetof(Mgmt__PoolReintReq, target_idx), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, total_targets), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "active_targets", 5, - PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolReintReq, n_svc_ranks), - offsetof(Mgmt__PoolReintReq, svc_ranks), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, active_targets), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tier_bytes", + "disabled_targets", 6, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolReintReq, n_tier_bytes), - offsetof(Mgmt__PoolReintReq, tier_bytes), + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, disabled_targets), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mem_ratio", + "rebuild", 7, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_FLOAT, + PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolReintReq, mem_ratio), + offsetof(Mgmt__PoolQueryResp, rebuild), + &mgmt__pool_rebuild_status__descriptor, NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "tier_stats", + 8, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolQueryResp, n_tier_stats), + offsetof(Mgmt__PoolQueryResp, tier_stats), + &mgmt__storage_usage_stats__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__pool_reint_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 6, /* field[6] = mem_ratio */ - 2, /* field[2] = rank */ - 4, /* field[4] = svc_ranks */ - 0, /* field[0] = sys */ - 3, /* field[3] = target_idx */ - 5, /* field[5] = tier_bytes */ -}; -static const ProtobufCIntRange mgmt__pool_reint_req__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 7 } -}; -const ProtobufCMessageDescriptor mgmt__pool_reint_req__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolReintReq", - "PoolReintReq", - "Mgmt__PoolReintReq", - "mgmt", - sizeof(Mgmt__PoolReintReq), - 7, - mgmt__pool_reint_req__field_descriptors, - mgmt__pool_reint_req__field_indices_by_name, - 1, mgmt__pool_reint_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_reint_req__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__pool_reint_resp__field_descriptors[1] = -{ { - "status", - 1, + "version", + 10, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolReintResp, status), + offsetof(Mgmt__PoolQueryResp, version), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__pool_reint_resp__field_indices_by_name[] = { - 0, /* field[0] = status */ -}; -static const ProtobufCIntRange mgmt__pool_reint_resp__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor mgmt__pool_reint_resp__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolReintResp", - "PoolReintResp", - "Mgmt__PoolReintResp", - "mgmt", - sizeof(Mgmt__PoolReintResp), - 1, - mgmt__pool_reint_resp__field_descriptors, - mgmt__pool_reint_resp__field_indices_by_name, - 1, mgmt__pool_reint_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_reint_resp__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_pools_req__field_descriptors[1] = -{ { - "sys", - 1, + "leader", + 11, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsReq, sys), + offsetof(Mgmt__PoolQueryResp, leader), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__list_pools_req__field_indices_by_name[] = { - 0, /* field[0] = sys */ -}; -static const ProtobufCIntRange mgmt__list_pools_req__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor mgmt__list_pools_req__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListPoolsReq", - "ListPoolsReq", - "Mgmt__ListPoolsReq", - "mgmt", - sizeof(Mgmt__ListPoolsReq), - 1, - mgmt__list_pools_req__field_descriptors, - mgmt__list_pools_req__field_indices_by_name, - 1, mgmt__list_pools_req__number_ranges, - (ProtobufCMessageInit) mgmt__list_pools_req__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_pools_resp__pool__field_descriptors[5] = -{ { - "uuid", - 1, + "enabled_ranks", + 12, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, enabled_ranks), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "disabled_ranks", + 13, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp__Pool, uuid), + offsetof(Mgmt__PoolQueryResp, disabled_ranks), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "label", - 2, + "total_engines", + 14, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp__Pool, label), + offsetof(Mgmt__PoolQueryResp, total_engines), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_reps", - 3, - PROTOBUF_C_LABEL_REPEATED, + "pool_layout_ver", + 15, + PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__ListPoolsResp__Pool, n_svc_reps), - offsetof(Mgmt__ListPoolsResp__Pool, svc_reps), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, pool_layout_ver), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "state", - 4, + "upgrade_layout_ver", + 16, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp__Pool, state), + offsetof(Mgmt__PoolQueryResp, upgrade_layout_ver), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "rebuild_state", - 5, + "state", + 17, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp__Pool, rebuild_state), + offsetof(Mgmt__PoolQueryResp, state), + &mgmt__pool_service_state__descriptor, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__list_pools_resp__pool__field_indices_by_name[] = { - 1, /* field[1] = label */ - 4, /* field[4] = rebuild_state */ - 3, /* field[3] = state */ - 2, /* field[2] = svc_reps */ - 0, /* field[0] = uuid */ -}; -static const ProtobufCIntRange mgmt__list_pools_resp__pool__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 5 } -}; -const ProtobufCMessageDescriptor mgmt__list_pools_resp__pool__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListPoolsResp.Pool", - "Pool", - "Mgmt__ListPoolsResp__Pool", - "mgmt", - sizeof(Mgmt__ListPoolsResp__Pool), - 5, - mgmt__list_pools_resp__pool__field_descriptors, - mgmt__list_pools_resp__pool__field_indices_by_name, - 1, mgmt__list_pools_resp__pool__number_ranges, - (ProtobufCMessageInit) mgmt__list_pools_resp__pool__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_pools_resp__field_descriptors[3] = -{ { - "status", - 1, + "svc_ldr", + 18, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp, status), + offsetof(Mgmt__PoolQueryResp, svc_ldr), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "pools", - 2, + "svc_reps", + 19, PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__ListPoolsResp, n_pools), - offsetof(Mgmt__ListPoolsResp, pools), - &mgmt__list_pools_resp__pool__descriptor, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolQueryResp, n_svc_reps), + offsetof(Mgmt__PoolQueryResp, svc_reps), NULL, - 0, /* flags */ + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "data_version", - 3, + "query_mask", + 20, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__ListPoolsResp, data_version), + offsetof(Mgmt__PoolQueryResp, query_mask), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__list_pools_resp__field_indices_by_name[] = { - 2, /* field[2] = data_version */ - 1, /* field[1] = pools */ - 0, /* field[0] = status */ -}; -static const ProtobufCIntRange mgmt__list_pools_resp__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor mgmt__list_pools_resp__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListPoolsResp", - "ListPoolsResp", - "Mgmt__ListPoolsResp", - "mgmt", - sizeof(Mgmt__ListPoolsResp), - 3, - mgmt__list_pools_resp__field_descriptors, - mgmt__list_pools_resp__field_indices_by_name, - 1, mgmt__list_pools_resp__number_ranges, - (ProtobufCMessageInit) mgmt__list_pools_resp__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_cont_req__field_descriptors[3] = -{ { - "sys", - 1, + "mem_file_bytes", + 21, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__ListContReq, sys), + offsetof(Mgmt__PoolQueryResp, mem_file_bytes), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", - 2, + "dead_ranks", + 22, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__ListContReq, id), + offsetof(Mgmt__PoolQueryResp, dead_ranks), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", - 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__ListContReq, n_svc_ranks), - offsetof(Mgmt__ListContReq, svc_ranks), + "md_on_ssd_active", + 23, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryResp, md_on_ssd_active), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__list_cont_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 2, /* field[2] = svc_ranks */ - 0, /* field[0] = sys */ -}; -static const ProtobufCIntRange mgmt__list_cont_req__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor mgmt__list_cont_req__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListContReq", - "ListContReq", - "Mgmt__ListContReq", - "mgmt", - sizeof(Mgmt__ListContReq), - 3, - mgmt__list_cont_req__field_descriptors, - mgmt__list_cont_req__field_indices_by_name, - 1, mgmt__list_cont_req__number_ranges, - (ProtobufCMessageInit) mgmt__list_cont_req__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_cont_resp__cont__field_descriptors[1] = -{ { - "uuid", - 1, + "self_heal_policy", + 24, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__ListContResp__Cont, uuid), + offsetof(Mgmt__PoolQueryResp, self_heal_policy), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, -}; -static const unsigned mgmt__list_cont_resp__cont__field_indices_by_name[] = { - 0, /* field[0] = uuid */ -}; -static const ProtobufCIntRange mgmt__list_cont_resp__cont__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor mgmt__list_cont_resp__cont__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListContResp.Cont", - "Cont", - "Mgmt__ListContResp__Cont", - "mgmt", - sizeof(Mgmt__ListContResp__Cont), - 1, - mgmt__list_cont_resp__cont__field_descriptors, - mgmt__list_cont_resp__cont__field_indices_by_name, - 1, mgmt__list_cont_resp__cont__number_ranges, - (ProtobufCMessageInit) mgmt__list_cont_resp__cont__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__list_cont_resp__field_descriptors[2] = -{ { - "status", - 1, + "sys_self_heal_policy", + 25, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__ListContResp, status), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "containers", - 2, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__ListContResp, n_containers), - offsetof(Mgmt__ListContResp, containers), - &mgmt__list_cont_resp__cont__descriptor, + offsetof(Mgmt__PoolQueryResp, sys_self_heal_policy), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__list_cont_resp__field_indices_by_name[] = { - 1, /* field[1] = containers */ +static const unsigned mgmt__pool_query_resp__field_indices_by_name[] = { + 4, /* field[4] = active_targets */ + 20, /* field[20] = dead_ranks */ + 11, /* field[11] = disabled_ranks */ + 5, /* field[5] = disabled_targets */ + 10, /* field[10] = enabled_ranks */ + 2, /* field[2] = label */ + 9, /* field[9] = leader */ + 21, /* field[21] = md_on_ssd_active */ + 19, /* field[19] = mem_file_bytes */ + 13, /* field[13] = pool_layout_ver */ + 18, /* field[18] = query_mask */ + 6, /* field[6] = rebuild */ + 22, /* field[22] = self_heal_policy */ + 15, /* field[15] = state */ 0, /* field[0] = status */ + 16, /* field[16] = svc_ldr */ + 17, /* field[17] = svc_reps */ + 23, /* field[23] = sys_self_heal_policy */ + 7, /* field[7] = tier_stats */ + 12, /* field[12] = total_engines */ + 3, /* field[3] = total_targets */ + 14, /* field[14] = upgrade_layout_ver */ + 1, /* field[1] = uuid */ + 8, /* field[8] = version */ }; -static const ProtobufCIntRange mgmt__list_cont_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_query_resp__number_ranges[2 + 1] = { { 1, 0 }, - { 0, 2 } + { 10, 8 }, + { 0, 24 } }; -const ProtobufCMessageDescriptor mgmt__list_cont_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_query_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.ListContResp", - "ListContResp", - "Mgmt__ListContResp", + "mgmt.PoolQueryResp", + "PoolQueryResp", + "Mgmt__PoolQueryResp", "mgmt", - sizeof(Mgmt__ListContResp), - 2, - mgmt__list_cont_resp__field_descriptors, - mgmt__list_cont_resp__field_indices_by_name, - 1, mgmt__list_cont_resp__number_ranges, - (ProtobufCMessageInit) mgmt__list_cont_resp__init, + sizeof(Mgmt__PoolQueryResp), + 24, + mgmt__pool_query_resp__field_descriptors, + mgmt__pool_query_resp__field_indices_by_name, + 2, mgmt__pool_query_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_query_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_query_req__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_property__field_descriptors[4] = { { - "sys", + "number", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryReq, sys), + offsetof(Mgmt__PoolProperty, number), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "strval", 2, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryReq, id), + offsetof(Mgmt__PoolProperty, value_case), + offsetof(Mgmt__PoolProperty, strval), NULL, &protobuf_c_empty_string, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "numval", 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolQueryReq, n_svc_ranks), - offsetof(Mgmt__PoolQueryReq, svc_ranks), + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + offsetof(Mgmt__PoolProperty, value_case), + offsetof(Mgmt__PoolProperty, numval), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "query_mask", + "byteval", 4, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryReq, query_mask), + PROTOBUF_C_TYPE_BYTES, + offsetof(Mgmt__PoolProperty, value_case), + offsetof(Mgmt__PoolProperty, byteval), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_query_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 3, /* field[3] = query_mask */ - 2, /* field[2] = svc_ranks */ - 0, /* field[0] = sys */ +static const unsigned mgmt__pool_property__field_indices_by_name[] = { + 3, /* field[3] = byteval */ + 0, /* field[0] = number */ + 2, /* field[2] = numval */ + 1, /* field[1] = strval */ }; -static const ProtobufCIntRange mgmt__pool_query_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_property__number_ranges[1 + 1] = { { 1, 0 }, { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__pool_query_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_property__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryReq", - "PoolQueryReq", - "Mgmt__PoolQueryReq", + "mgmt.PoolProperty", + "PoolProperty", + "Mgmt__PoolProperty", "mgmt", - sizeof(Mgmt__PoolQueryReq), + sizeof(Mgmt__PoolProperty), 4, - mgmt__pool_query_req__field_descriptors, - mgmt__pool_query_req__field_indices_by_name, - 1, mgmt__pool_query_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_query_req__init, + mgmt__pool_property__field_descriptors, + mgmt__pool_property__field_indices_by_name, + 1, mgmt__pool_property__number_ranges, + (ProtobufCMessageInit) mgmt__pool_property__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__storage_usage_stats__field_descriptors[6] = +static const ProtobufCFieldDescriptor mgmt__pool_set_prop_req__field_descriptors[4] = { { - "total", + "sys", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, total), - NULL, + offsetof(Mgmt__PoolSetPropReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "free", + "id", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, free), - NULL, + offsetof(Mgmt__PoolSetPropReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "min", + "properties", 3, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, min), - NULL, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolSetPropReq, n_properties), + offsetof(Mgmt__PoolSetPropReq, properties), + &mgmt__pool_property__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "max", + "svc_ranks", 4, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, max), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "mean", - 5, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, mean), - NULL, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolSetPropReq, n_svc_ranks), + offsetof(Mgmt__PoolSetPropReq, svc_ranks), NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "media_type", - 6, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_ENUM, - 0, /* quantifier_offset */ - offsetof(Mgmt__StorageUsageStats, media_type), - &mgmt__storage_media_type__descriptor, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__storage_usage_stats__field_indices_by_name[] = { - 1, /* field[1] = free */ - 3, /* field[3] = max */ - 4, /* field[4] = mean */ - 5, /* field[5] = media_type */ - 2, /* field[2] = min */ - 0, /* field[0] = total */ +static const unsigned mgmt__pool_set_prop_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = properties */ + 3, /* field[3] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__storage_usage_stats__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_set_prop_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 6 } + { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__storage_usage_stats__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_set_prop_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.StorageUsageStats", - "StorageUsageStats", - "Mgmt__StorageUsageStats", + "mgmt.PoolSetPropReq", + "PoolSetPropReq", + "Mgmt__PoolSetPropReq", "mgmt", - sizeof(Mgmt__StorageUsageStats), - 6, - mgmt__storage_usage_stats__field_descriptors, - mgmt__storage_usage_stats__field_indices_by_name, - 1, mgmt__storage_usage_stats__number_ranges, - (ProtobufCMessageInit) mgmt__storage_usage_stats__init, + sizeof(Mgmt__PoolSetPropReq), + 4, + mgmt__pool_set_prop_req__field_descriptors, + mgmt__pool_set_prop_req__field_indices_by_name, + 1, mgmt__pool_set_prop_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_set_prop_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCEnumValue mgmt__pool_rebuild_status__state__enum_values_by_number[7] = -{ - { "BUSY", "MGMT__POOL_REBUILD_STATUS__STATE__BUSY", 0 }, - { "IDLE", "MGMT__POOL_REBUILD_STATUS__STATE__IDLE", 1 }, - { "DONE", "MGMT__POOL_REBUILD_STATUS__STATE__DONE", 2 }, - { "STOPPING", "MGMT__POOL_REBUILD_STATUS__STATE__STOPPING", 3 }, - { "STOPPED", "MGMT__POOL_REBUILD_STATUS__STATE__STOPPED", 4 }, - { "FAILING", "MGMT__POOL_REBUILD_STATUS__STATE__FAILING", 5 }, - { "FAILED", "MGMT__POOL_REBUILD_STATUS__STATE__FAILED", 6 }, -}; -static const ProtobufCIntRange mgmt__pool_rebuild_status__state__value_ranges[] = { -{0, 0},{0, 7} -}; -static const ProtobufCEnumValueIndex mgmt__pool_rebuild_status__state__enum_values_by_name[7] = -{ - { "BUSY", 0 }, - { "DONE", 2 }, - { "FAILED", 6 }, - { "FAILING", 5 }, - { "IDLE", 1 }, - { "STOPPED", 4 }, - { "STOPPING", 3 }, -}; -const ProtobufCEnumDescriptor mgmt__pool_rebuild_status__state__descriptor = -{ - PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, - "mgmt.PoolRebuildStatus.State", - "State", - "Mgmt__PoolRebuildStatus__State", - "mgmt", - 7, - mgmt__pool_rebuild_status__state__enum_values_by_number, - 7, - mgmt__pool_rebuild_status__state__enum_values_by_name, - 1, - mgmt__pool_rebuild_status__state__value_ranges, - NULL,NULL,NULL,NULL /* reserved[1234] */ -}; -static const ProtobufCFieldDescriptor mgmt__pool_rebuild_status__field_descriptors[6] = +static const ProtobufCFieldDescriptor mgmt__pool_set_prop_resp__field_descriptors[1] = { { "status", @@ -3373,102 +4418,114 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_status__field_descripto PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, status), - NULL, + offsetof(Mgmt__PoolSetPropResp, status), NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "state", - 2, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_ENUM, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, state), - &mgmt__pool_rebuild_status__state__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_set_prop_resp__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__pool_set_prop_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor mgmt__pool_set_prop_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolSetPropResp", + "PoolSetPropResp", + "Mgmt__PoolSetPropResp", + "mgmt", + sizeof(Mgmt__PoolSetPropResp), + 1, + mgmt__pool_set_prop_resp__field_descriptors, + mgmt__pool_set_prop_resp__field_indices_by_name, + 1, mgmt__pool_set_prop_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_set_prop_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_get_prop_req__field_descriptors[4] = +{ { - "objects", - 3, + "sys", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, objects), - NULL, + offsetof(Mgmt__PoolGetPropReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "records", - 4, + "id", + 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, records), - NULL, + offsetof(Mgmt__PoolGetPropReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "derived_state", - 5, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_ENUM, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, derived_state), - &mgmt__pool_rebuild_status__state__descriptor, + "properties", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolGetPropReq, n_properties), + offsetof(Mgmt__PoolGetPropReq, properties), + &mgmt__pool_property__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "degraded", - 6, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStatus, degraded), + "svc_ranks", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolGetPropReq, n_svc_ranks), + offsetof(Mgmt__PoolGetPropReq, svc_ranks), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_rebuild_status__field_indices_by_name[] = { - 5, /* field[5] = degraded */ - 4, /* field[4] = derived_state */ - 2, /* field[2] = objects */ - 3, /* field[3] = records */ - 1, /* field[1] = state */ - 0, /* field[0] = status */ +static const unsigned mgmt__pool_get_prop_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = properties */ + 3, /* field[3] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_rebuild_status__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_get_prop_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 6 } + { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__pool_rebuild_status__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_get_prop_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolRebuildStatus", - "PoolRebuildStatus", - "Mgmt__PoolRebuildStatus", + "mgmt.PoolGetPropReq", + "PoolGetPropReq", + "Mgmt__PoolGetPropReq", "mgmt", - sizeof(Mgmt__PoolRebuildStatus), - 6, - mgmt__pool_rebuild_status__field_descriptors, - mgmt__pool_rebuild_status__field_indices_by_name, - 1, mgmt__pool_rebuild_status__number_ranges, - (ProtobufCMessageInit) mgmt__pool_rebuild_status__init, + sizeof(Mgmt__PoolGetPropReq), + 4, + mgmt__pool_get_prop_req__field_descriptors, + mgmt__pool_get_prop_req__field_indices_by_name, + 1, mgmt__pool_get_prop_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_prop_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_query_resp__field_descriptors[24] = +static const ProtobufCFieldDescriptor mgmt__pool_get_prop_resp__field_descriptors[2] = { { "status", @@ -3476,414 +4533,498 @@ static const ProtobufCFieldDescriptor mgmt__pool_query_resp__field_descriptors[2 PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, status), + offsetof(Mgmt__PoolGetPropResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "uuid", + "properties", 2, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, uuid), + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolGetPropResp, n_properties), + offsetof(Mgmt__PoolGetPropResp, properties), + &mgmt__pool_property__descriptor, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_get_prop_resp__field_indices_by_name[] = { + 1, /* field[1] = properties */ + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange mgmt__pool_get_prop_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor mgmt__pool_get_prop_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolGetPropResp", + "PoolGetPropResp", + "Mgmt__PoolGetPropResp", + "mgmt", + sizeof(Mgmt__PoolGetPropResp), + 2, + mgmt__pool_get_prop_resp__field_descriptors, + mgmt__pool_get_prop_resp__field_indices_by_name, + 1, mgmt__pool_get_prop_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_prop_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_upgrade_req__field_descriptors[3] = +{ { - "label", - 3, + "sys", + 1, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, label), + offsetof(Mgmt__PoolUpgradeReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "total_targets", - 4, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, total_targets), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "active_targets", - 5, + "id", + 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, active_targets), - NULL, + offsetof(Mgmt__PoolUpgradeReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "disabled_targets", - 6, - PROTOBUF_C_LABEL_NONE, + "svc_ranks", + 3, + PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, disabled_targets), + offsetof(Mgmt__PoolUpgradeReq, n_svc_ranks), + offsetof(Mgmt__PoolUpgradeReq, svc_ranks), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_upgrade_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = svc_ranks */ + 0, /* field[0] = sys */ +}; +static const ProtobufCIntRange mgmt__pool_upgrade_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor mgmt__pool_upgrade_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolUpgradeReq", + "PoolUpgradeReq", + "Mgmt__PoolUpgradeReq", + "mgmt", + sizeof(Mgmt__PoolUpgradeReq), + 3, + mgmt__pool_upgrade_req__field_descriptors, + mgmt__pool_upgrade_req__field_indices_by_name, + 1, mgmt__pool_upgrade_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_upgrade_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_query_target_req__field_descriptors[5] = +{ { - "rebuild", - 7, + "sys", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, rebuild), - &mgmt__pool_rebuild_status__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "tier_stats", - 8, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolQueryResp, n_tier_stats), - offsetof(Mgmt__PoolQueryResp, tier_stats), - &mgmt__storage_usage_stats__descriptor, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolQueryTargetReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "version", - 10, + "id", + 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, version), - NULL, + offsetof(Mgmt__PoolQueryTargetReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "leader", - 11, + "rank", + 3, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, leader), + offsetof(Mgmt__PoolQueryTargetReq, rank), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "enabled_ranks", - 12, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, enabled_ranks), + "targets", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolQueryTargetReq, n_targets), + offsetof(Mgmt__PoolQueryTargetReq, targets), NULL, - &protobuf_c_empty_string, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "disabled_ranks", - 13, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, disabled_ranks), NULL, - &protobuf_c_empty_string, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "total_engines", - 14, - PROTOBUF_C_LABEL_NONE, + "svc_ranks", + 5, + PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, total_engines), + offsetof(Mgmt__PoolQueryTargetReq, n_svc_ranks), + offsetof(Mgmt__PoolQueryTargetReq, svc_ranks), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_query_target_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = rank */ + 4, /* field[4] = svc_ranks */ + 0, /* field[0] = sys */ + 3, /* field[3] = targets */ +}; +static const ProtobufCIntRange mgmt__pool_query_target_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor mgmt__pool_query_target_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolQueryTargetReq", + "PoolQueryTargetReq", + "Mgmt__PoolQueryTargetReq", + "mgmt", + sizeof(Mgmt__PoolQueryTargetReq), + 5, + mgmt__pool_query_target_req__field_descriptors, + mgmt__pool_query_target_req__field_indices_by_name, + 1, mgmt__pool_query_target_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_query_target_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__storage_target_usage__field_descriptors[3] = +{ { - "pool_layout_ver", - 15, + "total", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, pool_layout_ver), + offsetof(Mgmt__StorageTargetUsage, total), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "upgrade_layout_ver", - 16, + "free", + 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, upgrade_layout_ver), + offsetof(Mgmt__StorageTargetUsage, free), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "state", - 17, + "media_type", + 3, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, state), - &mgmt__pool_service_state__descriptor, + offsetof(Mgmt__StorageTargetUsage, media_type), + &mgmt__storage_media_type__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__storage_target_usage__field_indices_by_name[] = { + 1, /* field[1] = free */ + 2, /* field[2] = media_type */ + 0, /* field[0] = total */ +}; +static const ProtobufCIntRange mgmt__storage_target_usage__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor mgmt__storage_target_usage__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.StorageTargetUsage", + "StorageTargetUsage", + "Mgmt__StorageTargetUsage", + "mgmt", + sizeof(Mgmt__StorageTargetUsage), + 3, + mgmt__storage_target_usage__field_descriptors, + mgmt__storage_target_usage__field_indices_by_name, + 1, mgmt__storage_target_usage__number_ranges, + (ProtobufCMessageInit) mgmt__storage_target_usage__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue mgmt__pool_query_target_info__target_state__enum_values_by_number[7] = +{ + { "STATE_UNKNOWN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__STATE_UNKNOWN", 0 }, + { "DOWN_OUT", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DOWN_OUT", 1 }, + { "DOWN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DOWN", 2 }, + { "UP", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__UP", 3 }, + { "UP_IN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__UP_IN", 4 }, + { "NEW", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__NEW", 5 }, + { "DRAIN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DRAIN", 6 }, +}; +static const ProtobufCIntRange mgmt__pool_query_target_info__target_state__value_ranges[] = { +{0, 0},{0, 7} +}; +static const ProtobufCEnumValueIndex mgmt__pool_query_target_info__target_state__enum_values_by_name[7] = +{ + { "DOWN", 2 }, + { "DOWN_OUT", 1 }, + { "DRAIN", 6 }, + { "NEW", 5 }, + { "STATE_UNKNOWN", 0 }, + { "UP", 3 }, + { "UP_IN", 4 }, +}; +const ProtobufCEnumDescriptor mgmt__pool_query_target_info__target_state__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "mgmt.PoolQueryTargetInfo.TargetState", + "TargetState", + "Mgmt__PoolQueryTargetInfo__TargetState", + "mgmt", + 7, + mgmt__pool_query_target_info__target_state__enum_values_by_number, + 7, + mgmt__pool_query_target_info__target_state__enum_values_by_name, + 1, + mgmt__pool_query_target_info__target_state__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_query_target_info__field_descriptors[4] = +{ { - "svc_ldr", - 18, + "state", + 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_ENUM, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, svc_ldr), - NULL, + offsetof(Mgmt__PoolQueryTargetInfo, state), + &mgmt__pool_query_target_info__target_state__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_reps", - 19, + "space", + 3, PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolQueryResp, n_svc_reps), - offsetof(Mgmt__PoolQueryResp, svc_reps), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "query_mask", - 20, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, query_mask), - NULL, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolQueryTargetInfo, n_space), + offsetof(Mgmt__PoolQueryTargetInfo, space), + &mgmt__storage_target_usage__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { "mem_file_bytes", - 21, + 4, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, mem_file_bytes), - NULL, + offsetof(Mgmt__PoolQueryTargetInfo, mem_file_bytes), NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "dead_ranks", - 22, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, dead_ranks), NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { "md_on_ssd_active", - 23, + 5, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_BOOL, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, md_on_ssd_active), + offsetof(Mgmt__PoolQueryTargetInfo, md_on_ssd_active), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned mgmt__pool_query_target_info__field_indices_by_name[] = { + 3, /* field[3] = md_on_ssd_active */ + 2, /* field[2] = mem_file_bytes */ + 1, /* field[1] = space */ + 0, /* field[0] = state */ +}; +static const ProtobufCIntRange mgmt__pool_query_target_info__number_ranges[1 + 1] = +{ + { 2, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor mgmt__pool_query_target_info__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolQueryTargetInfo", + "PoolQueryTargetInfo", + "Mgmt__PoolQueryTargetInfo", + "mgmt", + sizeof(Mgmt__PoolQueryTargetInfo), + 4, + mgmt__pool_query_target_info__field_descriptors, + mgmt__pool_query_target_info__field_indices_by_name, + 1, mgmt__pool_query_target_info__number_ranges, + (ProtobufCMessageInit) mgmt__pool_query_target_info__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_query_target_resp__field_descriptors[2] = +{ { - "self_heal_policy", - 24, + "status", + 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, self_heal_policy), + offsetof(Mgmt__PoolQueryTargetResp, status), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "sys_self_heal_policy", - 25, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryResp, sys_self_heal_policy), + "infos", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Mgmt__PoolQueryTargetResp, n_infos), + offsetof(Mgmt__PoolQueryTargetResp, infos), + &mgmt__pool_query_target_info__descriptor, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_query_resp__field_indices_by_name[] = { - 4, /* field[4] = active_targets */ - 20, /* field[20] = dead_ranks */ - 11, /* field[11] = disabled_ranks */ - 5, /* field[5] = disabled_targets */ - 10, /* field[10] = enabled_ranks */ - 2, /* field[2] = label */ - 9, /* field[9] = leader */ - 21, /* field[21] = md_on_ssd_active */ - 19, /* field[19] = mem_file_bytes */ - 13, /* field[13] = pool_layout_ver */ - 18, /* field[18] = query_mask */ - 6, /* field[6] = rebuild */ - 22, /* field[22] = self_heal_policy */ - 15, /* field[15] = state */ +static const unsigned mgmt__pool_query_target_resp__field_indices_by_name[] = { + 1, /* field[1] = infos */ 0, /* field[0] = status */ - 16, /* field[16] = svc_ldr */ - 17, /* field[17] = svc_reps */ - 23, /* field[23] = sys_self_heal_policy */ - 7, /* field[7] = tier_stats */ - 12, /* field[12] = total_engines */ - 3, /* field[3] = total_targets */ - 14, /* field[14] = upgrade_layout_ver */ - 1, /* field[1] = uuid */ - 8, /* field[8] = version */ }; -static const ProtobufCIntRange mgmt__pool_query_resp__number_ranges[2 + 1] = +static const ProtobufCIntRange mgmt__pool_query_target_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 10, 8 }, - { 0, 24 } + { 0, 2 } }; -const ProtobufCMessageDescriptor mgmt__pool_query_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_query_target_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryResp", - "PoolQueryResp", - "Mgmt__PoolQueryResp", + "mgmt.PoolQueryTargetResp", + "PoolQueryTargetResp", + "Mgmt__PoolQueryTargetResp", "mgmt", - sizeof(Mgmt__PoolQueryResp), - 24, - mgmt__pool_query_resp__field_descriptors, - mgmt__pool_query_resp__field_indices_by_name, - 2, mgmt__pool_query_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_query_resp__init, + sizeof(Mgmt__PoolQueryTargetResp), + 2, + mgmt__pool_query_target_resp__field_descriptors, + mgmt__pool_query_target_resp__field_indices_by_name, + 1, mgmt__pool_query_target_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_query_target_resp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_property__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_rebuild_start_req__field_descriptors[3] = { { - "number", + "sys", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolProperty, number), - NULL, + offsetof(Mgmt__PoolRebuildStartReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "strval", + "id", 2, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, - offsetof(Mgmt__PoolProperty, value_case), - offsetof(Mgmt__PoolProperty, strval), + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStartReq, id), NULL, &protobuf_c_empty_string, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "numval", + "svc_ranks", 3, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - offsetof(Mgmt__PoolProperty, value_case), - offsetof(Mgmt__PoolProperty, numval), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "byteval", - 4, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BYTES, - offsetof(Mgmt__PoolProperty, value_case), - offsetof(Mgmt__PoolProperty, byteval), + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolRebuildStartReq, n_svc_ranks), + offsetof(Mgmt__PoolRebuildStartReq, svc_ranks), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_property__field_indices_by_name[] = { - 3, /* field[3] = byteval */ - 0, /* field[0] = number */ - 2, /* field[2] = numval */ - 1, /* field[1] = strval */ +static const unsigned mgmt__pool_rebuild_start_req__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_property__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_rebuild_start_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 4 } + { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_property__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_rebuild_start_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolProperty", - "PoolProperty", - "Mgmt__PoolProperty", + "mgmt.PoolRebuildStartReq", + "PoolRebuildStartReq", + "Mgmt__PoolRebuildStartReq", "mgmt", - sizeof(Mgmt__PoolProperty), - 4, - mgmt__pool_property__field_descriptors, - mgmt__pool_property__field_indices_by_name, - 1, mgmt__pool_property__number_ranges, - (ProtobufCMessageInit) mgmt__pool_property__init, + sizeof(Mgmt__PoolRebuildStartReq), + 3, + mgmt__pool_rebuild_start_req__field_descriptors, + mgmt__pool_rebuild_start_req__field_indices_by_name, + 1, mgmt__pool_rebuild_start_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_rebuild_start_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_set_prop_req__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_rebuild_stop_req__field_descriptors[4] = { { "sys", @@ -3891,7 +5032,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_set_prop_req__field_descriptors PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSetPropReq, sys), + offsetof(Mgmt__PoolRebuildStopReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -3903,20 +5044,20 @@ static const ProtobufCFieldDescriptor mgmt__pool_set_prop_req__field_descriptors PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSetPropReq, id), + offsetof(Mgmt__PoolRebuildStopReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "properties", + "force", 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolSetPropReq, n_properties), - offsetof(Mgmt__PoolSetPropReq, properties), - &mgmt__pool_property__descriptor, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRebuildStopReq, force), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -3926,79 +5067,41 @@ static const ProtobufCFieldDescriptor mgmt__pool_set_prop_req__field_descriptors 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolSetPropReq, n_svc_ranks), - offsetof(Mgmt__PoolSetPropReq, svc_ranks), + offsetof(Mgmt__PoolRebuildStopReq, n_svc_ranks), + offsetof(Mgmt__PoolRebuildStopReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_set_prop_req__field_indices_by_name[] = { +static const unsigned mgmt__pool_rebuild_stop_req__field_indices_by_name[] = { + 2, /* field[2] = force */ 1, /* field[1] = id */ - 2, /* field[2] = properties */ 3, /* field[3] = svc_ranks */ 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_set_prop_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_rebuild_stop_req__number_ranges[1 + 1] = { { 1, 0 }, { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__pool_set_prop_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_rebuild_stop_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolSetPropReq", - "PoolSetPropReq", - "Mgmt__PoolSetPropReq", + "mgmt.PoolRebuildStopReq", + "PoolRebuildStopReq", + "Mgmt__PoolRebuildStopReq", "mgmt", - sizeof(Mgmt__PoolSetPropReq), + sizeof(Mgmt__PoolRebuildStopReq), 4, - mgmt__pool_set_prop_req__field_descriptors, - mgmt__pool_set_prop_req__field_indices_by_name, - 1, mgmt__pool_set_prop_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_set_prop_req__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor mgmt__pool_set_prop_resp__field_descriptors[1] = -{ - { - "status", - 1, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSetPropResp, status), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned mgmt__pool_set_prop_resp__field_indices_by_name[] = { - 0, /* field[0] = status */ -}; -static const ProtobufCIntRange mgmt__pool_set_prop_resp__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor mgmt__pool_set_prop_resp__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolSetPropResp", - "PoolSetPropResp", - "Mgmt__PoolSetPropResp", - "mgmt", - sizeof(Mgmt__PoolSetPropResp), - 1, - mgmt__pool_set_prop_resp__field_descriptors, - mgmt__pool_set_prop_resp__field_indices_by_name, - 1, mgmt__pool_set_prop_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_set_prop_resp__init, + mgmt__pool_rebuild_stop_req__field_descriptors, + mgmt__pool_rebuild_stop_req__field_indices_by_name, + 1, mgmt__pool_rebuild_stop_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_rebuild_stop_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_get_prop_req__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_self_heal_eval_req__field_descriptors[4] = { { "sys", @@ -4006,7 +5109,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_get_prop_req__field_descriptors PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolGetPropReq, sys), + offsetof(Mgmt__PoolSelfHealEvalReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -4018,179 +5121,193 @@ static const ProtobufCFieldDescriptor mgmt__pool_get_prop_req__field_descriptors PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolGetPropReq, id), + offsetof(Mgmt__PoolSelfHealEvalReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "properties", - 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolGetPropReq, n_properties), - offsetof(Mgmt__PoolGetPropReq, properties), - &mgmt__pool_property__descriptor, + "sys_prop_val", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolSelfHealEvalReq, sys_prop_val), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { "svc_ranks", - 4, + 5, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolGetPropReq, n_svc_ranks), - offsetof(Mgmt__PoolGetPropReq, svc_ranks), + offsetof(Mgmt__PoolSelfHealEvalReq, n_svc_ranks), + offsetof(Mgmt__PoolSelfHealEvalReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_get_prop_req__field_indices_by_name[] = { +static const unsigned mgmt__pool_self_heal_eval_req__field_indices_by_name[] = { 1, /* field[1] = id */ - 2, /* field[2] = properties */ 3, /* field[3] = svc_ranks */ 0, /* field[0] = sys */ + 2, /* field[2] = sys_prop_val */ }; -static const ProtobufCIntRange mgmt__pool_get_prop_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_self_heal_eval_req__number_ranges[2 + 1] = { { 1, 0 }, + { 4, 2 }, { 0, 4 } }; -const ProtobufCMessageDescriptor mgmt__pool_get_prop_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_self_heal_eval_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolGetPropReq", - "PoolGetPropReq", - "Mgmt__PoolGetPropReq", + "mgmt.PoolSelfHealEvalReq", + "PoolSelfHealEvalReq", + "Mgmt__PoolSelfHealEvalReq", "mgmt", - sizeof(Mgmt__PoolGetPropReq), + sizeof(Mgmt__PoolSelfHealEvalReq), 4, - mgmt__pool_get_prop_req__field_descriptors, - mgmt__pool_get_prop_req__field_indices_by_name, - 1, mgmt__pool_get_prop_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_get_prop_req__init, + mgmt__pool_self_heal_eval_req__field_descriptors, + mgmt__pool_self_heal_eval_req__field_indices_by_name, + 2, mgmt__pool_self_heal_eval_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_self_heal_eval_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_get_prop_resp__field_descriptors[2] = +static const ProtobufCFieldDescriptor mgmt__pool_get_careq__field_descriptors[3] = { { - "status", + "sys", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_INT32, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolGetPropResp, status), - NULL, + offsetof(Mgmt__PoolGetCAReq, sys), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "properties", + "id", 2, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolGetPropResp, n_properties), - offsetof(Mgmt__PoolGetPropResp, properties), - &mgmt__pool_property__descriptor, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolGetCAReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "svc_ranks", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolGetCAReq, n_svc_ranks), + offsetof(Mgmt__PoolGetCAReq, svc_ranks), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; -static const unsigned mgmt__pool_get_prop_resp__field_indices_by_name[] = { - 1, /* field[1] = properties */ - 0, /* field[0] = status */ +static const unsigned mgmt__pool_get_careq__field_indices_by_name[] = { + 1, /* field[1] = id */ + 2, /* field[2] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_get_prop_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_get_careq__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_get_prop_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_get_careq__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolGetPropResp", - "PoolGetPropResp", - "Mgmt__PoolGetPropResp", + "mgmt.PoolGetCAReq", + "PoolGetCAReq", + "Mgmt__PoolGetCAReq", "mgmt", - sizeof(Mgmt__PoolGetPropResp), - 2, - mgmt__pool_get_prop_resp__field_descriptors, - mgmt__pool_get_prop_resp__field_indices_by_name, - 1, mgmt__pool_get_prop_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_get_prop_resp__init, + sizeof(Mgmt__PoolGetCAReq), + 3, + mgmt__pool_get_careq__field_descriptors, + mgmt__pool_get_careq__field_indices_by_name, + 1, mgmt__pool_get_careq__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_careq__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_upgrade_req__field_descriptors[3] = +static const ProtobufCFieldDescriptor mgmt__pool_get_caresp__field_descriptors[3] = { { - "sys", + "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolUpgradeReq, sys), + offsetof(Mgmt__PoolGetCAResp, status), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "ca_bundle", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_BYTES, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolUpgradeReq, id), + offsetof(Mgmt__PoolGetCAResp, ca_bundle), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "pool_uuid", 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolUpgradeReq, n_svc_ranks), - offsetof(Mgmt__PoolUpgradeReq, svc_ranks), - NULL, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolGetCAResp, pool_uuid), NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + &protobuf_c_empty_string, + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_upgrade_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 2, /* field[2] = svc_ranks */ - 0, /* field[0] = sys */ +static const unsigned mgmt__pool_get_caresp__field_indices_by_name[] = { + 1, /* field[1] = ca_bundle */ + 2, /* field[2] = pool_uuid */ + 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__pool_upgrade_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_get_caresp__number_ranges[1 + 1] = { { 1, 0 }, { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_upgrade_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_get_caresp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolUpgradeReq", - "PoolUpgradeReq", - "Mgmt__PoolUpgradeReq", + "mgmt.PoolGetCAResp", + "PoolGetCAResp", + "Mgmt__PoolGetCAResp", "mgmt", - sizeof(Mgmt__PoolUpgradeReq), + sizeof(Mgmt__PoolGetCAResp), 3, - mgmt__pool_upgrade_req__field_descriptors, - mgmt__pool_upgrade_req__field_indices_by_name, - 1, mgmt__pool_upgrade_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_upgrade_req__init, + mgmt__pool_get_caresp__field_descriptors, + mgmt__pool_get_caresp__field_indices_by_name, + 1, mgmt__pool_get_caresp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_caresp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_query_target_req__field_descriptors[5] = +static const ProtobufCFieldDescriptor mgmt__pool_add_careq__field_descriptors[5] = { { "sys", @@ -4198,7 +5315,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_query_target_req__field_descrip PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetReq, sys), + offsetof(Mgmt__PoolAddCAReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -4210,256 +5327,218 @@ static const ProtobufCFieldDescriptor mgmt__pool_query_target_req__field_descrip PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetReq, id), + offsetof(Mgmt__PoolAddCAReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "rank", + "cert_pem", 3, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_BYTES, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetReq, rank), + offsetof(Mgmt__PoolAddCAReq, cert_pem), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "targets", + "svc_ranks", 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolQueryTargetReq, n_targets), - offsetof(Mgmt__PoolQueryTargetReq, targets), + offsetof(Mgmt__PoolAddCAReq, n_svc_ranks), + offsetof(Mgmt__PoolAddCAReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", + "replace", 5, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolQueryTargetReq, n_svc_ranks), - offsetof(Mgmt__PoolQueryTargetReq, svc_ranks), + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolAddCAReq, replace), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_query_target_req__field_indices_by_name[] = { +static const unsigned mgmt__pool_add_careq__field_indices_by_name[] = { + 2, /* field[2] = cert_pem */ 1, /* field[1] = id */ - 2, /* field[2] = rank */ - 4, /* field[4] = svc_ranks */ + 4, /* field[4] = replace */ + 3, /* field[3] = svc_ranks */ 0, /* field[0] = sys */ - 3, /* field[3] = targets */ }; -static const ProtobufCIntRange mgmt__pool_query_target_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_add_careq__number_ranges[1 + 1] = { { 1, 0 }, { 0, 5 } }; -const ProtobufCMessageDescriptor mgmt__pool_query_target_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_add_careq__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryTargetReq", - "PoolQueryTargetReq", - "Mgmt__PoolQueryTargetReq", + "mgmt.PoolAddCAReq", + "PoolAddCAReq", + "Mgmt__PoolAddCAReq", "mgmt", - sizeof(Mgmt__PoolQueryTargetReq), + sizeof(Mgmt__PoolAddCAReq), 5, - mgmt__pool_query_target_req__field_descriptors, - mgmt__pool_query_target_req__field_indices_by_name, - 1, mgmt__pool_query_target_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_query_target_req__init, + mgmt__pool_add_careq__field_descriptors, + mgmt__pool_add_careq__field_indices_by_name, + 1, mgmt__pool_add_careq__number_ranges, + (ProtobufCMessageInit) mgmt__pool_add_careq__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__storage_target_usage__field_descriptors[3] = +static const ProtobufCFieldDescriptor mgmt__pool_add_caresp__field_descriptors[2] = { { - "total", + "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__StorageTargetUsage, total), + offsetof(Mgmt__PoolAddCAResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "free", + "pool_uuid", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Mgmt__StorageTargetUsage, free), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "media_type", - 3, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_ENUM, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__StorageTargetUsage, media_type), - &mgmt__storage_media_type__descriptor, + offsetof(Mgmt__PoolAddCAResp, pool_uuid), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__storage_target_usage__field_indices_by_name[] = { - 1, /* field[1] = free */ - 2, /* field[2] = media_type */ - 0, /* field[0] = total */ +static const unsigned mgmt__pool_add_caresp__field_indices_by_name[] = { + 1, /* field[1] = pool_uuid */ + 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__storage_target_usage__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_add_caresp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 3 } + { 0, 2 } }; -const ProtobufCMessageDescriptor mgmt__storage_target_usage__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_add_caresp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.StorageTargetUsage", - "StorageTargetUsage", - "Mgmt__StorageTargetUsage", + "mgmt.PoolAddCAResp", + "PoolAddCAResp", + "Mgmt__PoolAddCAResp", "mgmt", - sizeof(Mgmt__StorageTargetUsage), - 3, - mgmt__storage_target_usage__field_descriptors, - mgmt__storage_target_usage__field_indices_by_name, - 1, mgmt__storage_target_usage__number_ranges, - (ProtobufCMessageInit) mgmt__storage_target_usage__init, + sizeof(Mgmt__PoolAddCAResp), + 2, + mgmt__pool_add_caresp__field_descriptors, + mgmt__pool_add_caresp__field_indices_by_name, + 1, mgmt__pool_add_caresp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_add_caresp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCEnumValue mgmt__pool_query_target_info__target_state__enum_values_by_number[7] = -{ - { "STATE_UNKNOWN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__STATE_UNKNOWN", 0 }, - { "DOWN_OUT", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DOWN_OUT", 1 }, - { "DOWN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DOWN", 2 }, - { "UP", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__UP", 3 }, - { "UP_IN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__UP_IN", 4 }, - { "NEW", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__NEW", 5 }, - { "DRAIN", "MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DRAIN", 6 }, -}; -static const ProtobufCIntRange mgmt__pool_query_target_info__target_state__value_ranges[] = { -{0, 0},{0, 7} -}; -static const ProtobufCEnumValueIndex mgmt__pool_query_target_info__target_state__enum_values_by_name[7] = -{ - { "DOWN", 2 }, - { "DOWN_OUT", 1 }, - { "DRAIN", 6 }, - { "NEW", 5 }, - { "STATE_UNKNOWN", 0 }, - { "UP", 3 }, - { "UP_IN", 4 }, -}; -const ProtobufCEnumDescriptor mgmt__pool_query_target_info__target_state__descriptor = -{ - PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryTargetInfo.TargetState", - "TargetState", - "Mgmt__PoolQueryTargetInfo__TargetState", - "mgmt", - 7, - mgmt__pool_query_target_info__target_state__enum_values_by_number, - 7, - mgmt__pool_query_target_info__target_state__enum_values_by_name, - 1, - mgmt__pool_query_target_info__target_state__value_ranges, - NULL,NULL,NULL,NULL /* reserved[1234] */ -}; -static const ProtobufCFieldDescriptor mgmt__pool_query_target_info__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_remove_careq__field_descriptors[5] = { { - "state", + "sys", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRemoveCAReq, sys), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "id", 2, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_ENUM, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetInfo, state), - &mgmt__pool_query_target_info__target_state__descriptor, + offsetof(Mgmt__PoolRemoveCAReq, id), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "space", + "fingerprint", 3, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolQueryTargetInfo, n_space), - offsetof(Mgmt__PoolQueryTargetInfo, space), - &mgmt__storage_target_usage__descriptor, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRemoveCAReq, fingerprint), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mem_file_bytes", + "all", 4, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_BOOL, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetInfo, mem_file_bytes), + offsetof(Mgmt__PoolRemoveCAReq, all), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "md_on_ssd_active", + "svc_ranks", 5, - PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, - 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetInfo, md_on_ssd_active), + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_UINT32, + offsetof(Mgmt__PoolRemoveCAReq, n_svc_ranks), + offsetof(Mgmt__PoolRemoveCAReq, svc_ranks), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_query_target_info__field_indices_by_name[] = { - 3, /* field[3] = md_on_ssd_active */ - 2, /* field[2] = mem_file_bytes */ - 1, /* field[1] = space */ - 0, /* field[0] = state */ +static const unsigned mgmt__pool_remove_careq__field_indices_by_name[] = { + 3, /* field[3] = all */ + 2, /* field[2] = fingerprint */ + 1, /* field[1] = id */ + 4, /* field[4] = svc_ranks */ + 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_query_target_info__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_remove_careq__number_ranges[1 + 1] = { - { 2, 0 }, - { 0, 4 } + { 1, 0 }, + { 0, 5 } }; -const ProtobufCMessageDescriptor mgmt__pool_query_target_info__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_remove_careq__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryTargetInfo", - "PoolQueryTargetInfo", - "Mgmt__PoolQueryTargetInfo", + "mgmt.PoolRemoveCAReq", + "PoolRemoveCAReq", + "Mgmt__PoolRemoveCAReq", "mgmt", - sizeof(Mgmt__PoolQueryTargetInfo), - 4, - mgmt__pool_query_target_info__field_descriptors, - mgmt__pool_query_target_info__field_indices_by_name, - 1, mgmt__pool_query_target_info__number_ranges, - (ProtobufCMessageInit) mgmt__pool_query_target_info__init, + sizeof(Mgmt__PoolRemoveCAReq), + 5, + mgmt__pool_remove_careq__field_descriptors, + mgmt__pool_remove_careq__field_indices_by_name, + 1, mgmt__pool_remove_careq__number_ranges, + (ProtobufCMessageInit) mgmt__pool_remove_careq__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_query_target_resp__field_descriptors[2] = +static const ProtobufCFieldDescriptor mgmt__pool_remove_caresp__field_descriptors[3] = { { "status", @@ -4467,50 +5546,63 @@ static const ProtobufCFieldDescriptor mgmt__pool_query_target_resp__field_descri PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolQueryTargetResp, status), + offsetof(Mgmt__PoolRemoveCAResp, status), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "infos", + "certs_removed", 2, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Mgmt__PoolQueryTargetResp, n_infos), - offsetof(Mgmt__PoolQueryTargetResp, infos), - &mgmt__pool_query_target_info__descriptor, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRemoveCAResp, certs_removed), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "pool_uuid", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRemoveCAResp, pool_uuid), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_query_target_resp__field_indices_by_name[] = { - 1, /* field[1] = infos */ +static const unsigned mgmt__pool_remove_caresp__field_indices_by_name[] = { + 1, /* field[1] = certs_removed */ + 2, /* field[2] = pool_uuid */ 0, /* field[0] = status */ }; -static const ProtobufCIntRange mgmt__pool_query_target_resp__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_remove_caresp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_query_target_resp__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_remove_caresp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolQueryTargetResp", - "PoolQueryTargetResp", - "Mgmt__PoolQueryTargetResp", + "mgmt.PoolRemoveCAResp", + "PoolRemoveCAResp", + "Mgmt__PoolRemoveCAResp", "mgmt", - sizeof(Mgmt__PoolQueryTargetResp), - 2, - mgmt__pool_query_target_resp__field_descriptors, - mgmt__pool_query_target_resp__field_indices_by_name, - 1, mgmt__pool_query_target_resp__number_ranges, - (ProtobufCMessageInit) mgmt__pool_query_target_resp__init, + sizeof(Mgmt__PoolRemoveCAResp), + 3, + mgmt__pool_remove_caresp__field_descriptors, + mgmt__pool_remove_caresp__field_indices_by_name, + 1, mgmt__pool_remove_caresp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_remove_caresp__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_rebuild_start_req__field_descriptors[3] = +static const ProtobufCFieldDescriptor mgmt__pool_get_cert_watermarks_req__field_descriptors[3] = { { "sys", @@ -4518,7 +5610,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_start_req__field_descri PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStartReq, sys), + offsetof(Mgmt__PoolGetCertWatermarksReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -4530,7 +5622,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_start_req__field_descri PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStartReq, id), + offsetof(Mgmt__PoolGetCertWatermarksReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -4541,40 +5633,134 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_start_req__field_descri 3, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolRebuildStartReq, n_svc_ranks), - offsetof(Mgmt__PoolRebuildStartReq, svc_ranks), + offsetof(Mgmt__PoolGetCertWatermarksReq, n_svc_ranks), + offsetof(Mgmt__PoolGetCertWatermarksReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_rebuild_start_req__field_indices_by_name[] = { +static const unsigned mgmt__pool_get_cert_watermarks_req__field_indices_by_name[] = { 1, /* field[1] = id */ 2, /* field[2] = svc_ranks */ 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_rebuild_start_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_get_cert_watermarks_req__number_ranges[1 + 1] = { { 1, 0 }, { 0, 3 } }; -const ProtobufCMessageDescriptor mgmt__pool_rebuild_start_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_get_cert_watermarks_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolRebuildStartReq", - "PoolRebuildStartReq", - "Mgmt__PoolRebuildStartReq", + "mgmt.PoolGetCertWatermarksReq", + "PoolGetCertWatermarksReq", + "Mgmt__PoolGetCertWatermarksReq", "mgmt", - sizeof(Mgmt__PoolRebuildStartReq), + sizeof(Mgmt__PoolGetCertWatermarksReq), 3, - mgmt__pool_rebuild_start_req__field_descriptors, - mgmt__pool_rebuild_start_req__field_indices_by_name, - 1, mgmt__pool_rebuild_start_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_rebuild_start_req__init, + mgmt__pool_get_cert_watermarks_req__field_descriptors, + mgmt__pool_get_cert_watermarks_req__field_indices_by_name, + 1, mgmt__pool_get_cert_watermarks_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_cert_watermarks_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_rebuild_stop_req__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_get_cert_watermarks_resp__field_descriptors[3] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolGetCertWatermarksResp, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "watermarks", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolGetCertWatermarksResp, watermarks), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "pool_uuid", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolGetCertWatermarksResp, pool_uuid), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned mgmt__pool_get_cert_watermarks_resp__field_indices_by_name[] = { + 2, /* field[2] = pool_uuid */ + 0, /* field[0] = status */ + 1, /* field[1] = watermarks */ +}; +static const ProtobufCIntRange mgmt__pool_get_cert_watermarks_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor mgmt__pool_get_cert_watermarks_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "mgmt.PoolGetCertWatermarksResp", + "PoolGetCertWatermarksResp", + "Mgmt__PoolGetCertWatermarksResp", + "mgmt", + sizeof(Mgmt__PoolGetCertWatermarksResp), + 3, + mgmt__pool_get_cert_watermarks_resp__field_descriptors, + mgmt__pool_get_cert_watermarks_resp__field_indices_by_name, + 1, mgmt__pool_get_cert_watermarks_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_get_cert_watermarks_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue mgmt__pool_revoke_client_req__evict_mode__enum_values_by_number[3] = +{ + { "EVICT_DEFAULT", "MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_DEFAULT", 0 }, + { "EVICT_POOL_WIDE", "MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_POOL_WIDE", 1 }, + { "EVICT_NONE", "MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_NONE", 2 }, +}; +static const ProtobufCIntRange mgmt__pool_revoke_client_req__evict_mode__value_ranges[] = { +{0, 0},{0, 3} +}; +static const ProtobufCEnumValueIndex mgmt__pool_revoke_client_req__evict_mode__enum_values_by_name[3] = +{ + { "EVICT_DEFAULT", 0 }, + { "EVICT_NONE", 2 }, + { "EVICT_POOL_WIDE", 1 }, +}; +const ProtobufCEnumDescriptor mgmt__pool_revoke_client_req__evict_mode__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "mgmt.PoolRevokeClientReq.EvictMode", + "EvictMode", + "Mgmt__PoolRevokeClientReq__EvictMode", + "mgmt", + 3, + mgmt__pool_revoke_client_req__evict_mode__enum_values_by_number, + 3, + mgmt__pool_revoke_client_req__evict_mode__enum_values_by_name, + 1, + mgmt__pool_revoke_client_req__evict_mode__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor mgmt__pool_revoke_client_req__field_descriptors[5] = { { "sys", @@ -4582,7 +5768,7 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_stop_req__field_descrip PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStopReq, sys), + offsetof(Mgmt__PoolRevokeClientReq, sys), NULL, &protobuf_c_empty_string, 0, /* flags */ @@ -4594,21 +5780,21 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_stop_req__field_descrip PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStopReq, id), + offsetof(Mgmt__PoolRevokeClientReq, id), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "force", + "cn", 3, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_BOOL, + PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolRebuildStopReq, force), - NULL, + offsetof(Mgmt__PoolRevokeClientReq, cn), NULL, + &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, @@ -4617,116 +5803,141 @@ static const ProtobufCFieldDescriptor mgmt__pool_rebuild_stop_req__field_descrip 4, PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolRebuildStopReq, n_svc_ranks), - offsetof(Mgmt__PoolRebuildStopReq, svc_ranks), + offsetof(Mgmt__PoolRevokeClientReq, n_svc_ranks), + offsetof(Mgmt__PoolRevokeClientReq, svc_ranks), NULL, NULL, 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "evict_mode", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRevokeClientReq, evict_mode), + &mgmt__pool_revoke_client_req__evict_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; -static const unsigned mgmt__pool_rebuild_stop_req__field_indices_by_name[] = { - 2, /* field[2] = force */ +static const unsigned mgmt__pool_revoke_client_req__field_indices_by_name[] = { + 2, /* field[2] = cn */ + 4, /* field[4] = evict_mode */ 1, /* field[1] = id */ 3, /* field[3] = svc_ranks */ 0, /* field[0] = sys */ }; -static const ProtobufCIntRange mgmt__pool_rebuild_stop_req__number_ranges[1 + 1] = +static const ProtobufCIntRange mgmt__pool_revoke_client_req__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 4 } + { 0, 5 } }; -const ProtobufCMessageDescriptor mgmt__pool_rebuild_stop_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_revoke_client_req__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolRebuildStopReq", - "PoolRebuildStopReq", - "Mgmt__PoolRebuildStopReq", + "mgmt.PoolRevokeClientReq", + "PoolRevokeClientReq", + "Mgmt__PoolRevokeClientReq", "mgmt", - sizeof(Mgmt__PoolRebuildStopReq), - 4, - mgmt__pool_rebuild_stop_req__field_descriptors, - mgmt__pool_rebuild_stop_req__field_indices_by_name, - 1, mgmt__pool_rebuild_stop_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_rebuild_stop_req__init, + sizeof(Mgmt__PoolRevokeClientReq), + 5, + mgmt__pool_revoke_client_req__field_descriptors, + mgmt__pool_revoke_client_req__field_indices_by_name, + 1, mgmt__pool_revoke_client_req__number_ranges, + (ProtobufCMessageInit) mgmt__pool_revoke_client_req__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor mgmt__pool_self_heal_eval_req__field_descriptors[4] = +static const ProtobufCFieldDescriptor mgmt__pool_revoke_client_resp__field_descriptors[5] = { { - "sys", + "status", 1, PROTOBUF_C_LABEL_NONE, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_INT32, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSelfHealEvalReq, sys), + offsetof(Mgmt__PoolRevokeClientResp, status), + NULL, NULL, - &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "id", + "watermark_rfc3339", 2, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSelfHealEvalReq, id), + offsetof(Mgmt__PoolRevokeClientResp, watermark_rfc3339), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "sys_prop_val", - 4, + "pool_uuid", + 3, PROTOBUF_C_LABEL_NONE, PROTOBUF_C_TYPE_STRING, 0, /* quantifier_offset */ - offsetof(Mgmt__PoolSelfHealEvalReq, sys_prop_val), + offsetof(Mgmt__PoolRevokeClientResp, pool_uuid), NULL, &protobuf_c_empty_string, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "svc_ranks", - 5, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_UINT32, - offsetof(Mgmt__PoolSelfHealEvalReq, n_svc_ranks), - offsetof(Mgmt__PoolSelfHealEvalReq, svc_ranks), + "handles_evicted_count", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRevokeClientResp, handles_evicted_count), NULL, NULL, - 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "evict_scope", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Mgmt__PoolRevokeClientResp, evict_scope), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned mgmt__pool_self_heal_eval_req__field_indices_by_name[] = { - 1, /* field[1] = id */ - 3, /* field[3] = svc_ranks */ - 0, /* field[0] = sys */ - 2, /* field[2] = sys_prop_val */ +static const unsigned mgmt__pool_revoke_client_resp__field_indices_by_name[] = { + 4, /* field[4] = evict_scope */ + 3, /* field[3] = handles_evicted_count */ + 2, /* field[2] = pool_uuid */ + 0, /* field[0] = status */ + 1, /* field[1] = watermark_rfc3339 */ }; -static const ProtobufCIntRange mgmt__pool_self_heal_eval_req__number_ranges[2 + 1] = +static const ProtobufCIntRange mgmt__pool_revoke_client_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 4, 2 }, - { 0, 4 } + { 0, 5 } }; -const ProtobufCMessageDescriptor mgmt__pool_self_heal_eval_req__descriptor = +const ProtobufCMessageDescriptor mgmt__pool_revoke_client_resp__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "mgmt.PoolSelfHealEvalReq", - "PoolSelfHealEvalReq", - "Mgmt__PoolSelfHealEvalReq", + "mgmt.PoolRevokeClientResp", + "PoolRevokeClientResp", + "Mgmt__PoolRevokeClientResp", "mgmt", - sizeof(Mgmt__PoolSelfHealEvalReq), - 4, - mgmt__pool_self_heal_eval_req__field_descriptors, - mgmt__pool_self_heal_eval_req__field_indices_by_name, - 2, mgmt__pool_self_heal_eval_req__number_ranges, - (ProtobufCMessageInit) mgmt__pool_self_heal_eval_req__init, + sizeof(Mgmt__PoolRevokeClientResp), + 5, + mgmt__pool_revoke_client_resp__field_descriptors, + mgmt__pool_revoke_client_resp__field_indices_by_name, + 1, mgmt__pool_revoke_client_resp__number_ranges, + (ProtobufCMessageInit) mgmt__pool_revoke_client_resp__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCEnumValue mgmt__storage_media_type__enum_values_by_number[2] = diff --git a/src/mgmt/pool.pb-c.h b/src/mgmt/pool.pb-c.h index 382c2d5e0f9..b7db0ff8f10 100644 --- a/src/mgmt/pool.pb-c.h +++ b/src/mgmt/pool.pb-c.h @@ -52,6 +52,16 @@ typedef struct _Mgmt__PoolQueryTargetResp Mgmt__PoolQueryTargetResp; typedef struct _Mgmt__PoolRebuildStartReq Mgmt__PoolRebuildStartReq; typedef struct _Mgmt__PoolRebuildStopReq Mgmt__PoolRebuildStopReq; typedef struct _Mgmt__PoolSelfHealEvalReq Mgmt__PoolSelfHealEvalReq; +typedef struct _Mgmt__PoolGetCAReq Mgmt__PoolGetCAReq; +typedef struct _Mgmt__PoolGetCAResp Mgmt__PoolGetCAResp; +typedef struct _Mgmt__PoolAddCAReq Mgmt__PoolAddCAReq; +typedef struct _Mgmt__PoolAddCAResp Mgmt__PoolAddCAResp; +typedef struct _Mgmt__PoolRemoveCAReq Mgmt__PoolRemoveCAReq; +typedef struct _Mgmt__PoolRemoveCAResp Mgmt__PoolRemoveCAResp; +typedef struct _Mgmt__PoolGetCertWatermarksReq Mgmt__PoolGetCertWatermarksReq; +typedef struct _Mgmt__PoolGetCertWatermarksResp Mgmt__PoolGetCertWatermarksResp; +typedef struct _Mgmt__PoolRevokeClientReq Mgmt__PoolRevokeClientReq; +typedef struct _Mgmt__PoolRevokeClientResp Mgmt__PoolRevokeClientResp; /* --- enums --- */ @@ -94,6 +104,21 @@ typedef enum _Mgmt__PoolQueryTargetInfo__TargetState { MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE__DRAIN = 6 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(MGMT__POOL_QUERY_TARGET_INFO__TARGET_STATE) } Mgmt__PoolQueryTargetInfo__TargetState; +typedef enum _Mgmt__PoolRevokeClientReq__EvictMode { + /* + * per-CN for node:, pool-wide for tenant: + */ + MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_DEFAULT = 0, + /* + * always evict all handles on the pool + */ + MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_POOL_WIDE = 1, + /* + * advance watermark, leave handles alive + */ + MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_NONE = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE) +} Mgmt__PoolRevokeClientReq__EvictMode; typedef enum _Mgmt__StorageMediaType { MGMT__STORAGE_MEDIA_TYPE__SCM = 0, MGMT__STORAGE_MEDIA_TYPE__NVME = 1 @@ -1240,6 +1265,171 @@ struct _Mgmt__PoolSelfHealEvalReq , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL } +/* + * PoolGetCAReq fetches the pool's CA bundle. + */ +struct _Mgmt__PoolGetCAReq +{ + ProtobufCMessage base; + char *sys; + char *id; + size_t n_svc_ranks; + uint32_t *svc_ranks; +}; +#define MGMT__POOL_GET_CAREQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_get_careq__descriptor) \ + , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL } + + +struct _Mgmt__PoolGetCAResp +{ + ProtobufCMessage base; + int32_t status; + ProtobufCBinaryData ca_bundle; + char *pool_uuid; +}; +#define MGMT__POOL_GET_CARESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_get_caresp__descriptor) \ + , 0, {0,NULL}, (char *)protobuf_c_empty_string } + + +/* + * PoolAddCAReq appends a CA certificate to the pool's CA bundle. + */ +struct _Mgmt__PoolAddCAReq +{ + ProtobufCMessage base; + char *sys; + char *id; + ProtobufCBinaryData cert_pem; + size_t n_svc_ranks; + uint32_t *svc_ranks; + /* + * clear existing bundle before append + */ + protobuf_c_boolean replace; +}; +#define MGMT__POOL_ADD_CAREQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_add_careq__descriptor) \ + , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, {0,NULL}, 0,NULL, 0 } + + +struct _Mgmt__PoolAddCAResp +{ + ProtobufCMessage base; + int32_t status; + char *pool_uuid; +}; +#define MGMT__POOL_ADD_CARESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_add_caresp__descriptor) \ + , 0, (char *)protobuf_c_empty_string } + + +/* + * PoolRemoveCAReq removes one or all CAs from the pool's CA bundle. + */ +struct _Mgmt__PoolRemoveCAReq +{ + ProtobufCMessage base; + char *sys; + char *id; + /* + * SHA-256 hex of the CA cert to remove + */ + char *fingerprint; + /* + * remove every CA in the bundle + */ + protobuf_c_boolean all; + size_t n_svc_ranks; + uint32_t *svc_ranks; +}; +#define MGMT__POOL_REMOVE_CAREQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_remove_careq__descriptor) \ + , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0, 0,NULL } + + +struct _Mgmt__PoolRemoveCAResp +{ + ProtobufCMessage base; + int32_t status; + int32_t certs_removed; + char *pool_uuid; +}; +#define MGMT__POOL_REMOVE_CARESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_remove_caresp__descriptor) \ + , 0, 0, (char *)protobuf_c_empty_string } + + +/* + * PoolGetCertWatermarksReq fetches the per-CN revocation watermarks blob. + */ +struct _Mgmt__PoolGetCertWatermarksReq +{ + ProtobufCMessage base; + char *sys; + char *id; + size_t n_svc_ranks; + uint32_t *svc_ranks; +}; +#define MGMT__POOL_GET_CERT_WATERMARKS_REQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_get_cert_watermarks_req__descriptor) \ + , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL } + + +struct _Mgmt__PoolGetCertWatermarksResp +{ + ProtobufCMessage base; + int32_t status; + /* + * JSON blob, may be empty + */ + ProtobufCBinaryData watermarks; + char *pool_uuid; +}; +#define MGMT__POOL_GET_CERT_WATERMARKS_RESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_get_cert_watermarks_resp__descriptor) \ + , 0, {0,NULL}, (char *)protobuf_c_empty_string } + + +/* + * PoolRevokeClientReq advances the pool's revocation watermark for a CN. + */ +struct _Mgmt__PoolRevokeClientReq +{ + ProtobufCMessage base; + char *sys; + char *id; + char *cn; + size_t n_svc_ranks; + uint32_t *svc_ranks; + Mgmt__PoolRevokeClientReq__EvictMode evict_mode; +}; +#define MGMT__POOL_REVOKE_CLIENT_REQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_revoke_client_req__descriptor) \ + , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, MGMT__POOL_REVOKE_CLIENT_REQ__EVICT_MODE__EVICT_DEFAULT } + + +struct _Mgmt__PoolRevokeClientResp +{ + ProtobufCMessage base; + int32_t status; + /* + * committed watermark in RFC3339 UTC + */ + char *watermark_rfc3339; + char *pool_uuid; + int32_t handles_evicted_count; + /* + * "machine" | "pool" | "none" + */ + char *evict_scope; +}; +#define MGMT__POOL_REVOKE_CLIENT_RESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&mgmt__pool_revoke_client_resp__descriptor) \ + , 0, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0, (char *)protobuf_c_empty_string } + + /* Mgmt__PoolCreateReq methods */ void mgmt__pool_create_req__init (Mgmt__PoolCreateReq *message); @@ -1911,6 +2101,196 @@ Mgmt__PoolSelfHealEvalReq * void mgmt__pool_self_heal_eval_req__free_unpacked (Mgmt__PoolSelfHealEvalReq *message, ProtobufCAllocator *allocator); +/* Mgmt__PoolGetCAReq methods */ +void mgmt__pool_get_careq__init + (Mgmt__PoolGetCAReq *message); +size_t mgmt__pool_get_careq__get_packed_size + (const Mgmt__PoolGetCAReq *message); +size_t mgmt__pool_get_careq__pack + (const Mgmt__PoolGetCAReq *message, + uint8_t *out); +size_t mgmt__pool_get_careq__pack_to_buffer + (const Mgmt__PoolGetCAReq *message, + ProtobufCBuffer *buffer); +Mgmt__PoolGetCAReq * + mgmt__pool_get_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_get_careq__free_unpacked + (Mgmt__PoolGetCAReq *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolGetCAResp methods */ +void mgmt__pool_get_caresp__init + (Mgmt__PoolGetCAResp *message); +size_t mgmt__pool_get_caresp__get_packed_size + (const Mgmt__PoolGetCAResp *message); +size_t mgmt__pool_get_caresp__pack + (const Mgmt__PoolGetCAResp *message, + uint8_t *out); +size_t mgmt__pool_get_caresp__pack_to_buffer + (const Mgmt__PoolGetCAResp *message, + ProtobufCBuffer *buffer); +Mgmt__PoolGetCAResp * + mgmt__pool_get_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_get_caresp__free_unpacked + (Mgmt__PoolGetCAResp *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolAddCAReq methods */ +void mgmt__pool_add_careq__init + (Mgmt__PoolAddCAReq *message); +size_t mgmt__pool_add_careq__get_packed_size + (const Mgmt__PoolAddCAReq *message); +size_t mgmt__pool_add_careq__pack + (const Mgmt__PoolAddCAReq *message, + uint8_t *out); +size_t mgmt__pool_add_careq__pack_to_buffer + (const Mgmt__PoolAddCAReq *message, + ProtobufCBuffer *buffer); +Mgmt__PoolAddCAReq * + mgmt__pool_add_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_add_careq__free_unpacked + (Mgmt__PoolAddCAReq *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolAddCAResp methods */ +void mgmt__pool_add_caresp__init + (Mgmt__PoolAddCAResp *message); +size_t mgmt__pool_add_caresp__get_packed_size + (const Mgmt__PoolAddCAResp *message); +size_t mgmt__pool_add_caresp__pack + (const Mgmt__PoolAddCAResp *message, + uint8_t *out); +size_t mgmt__pool_add_caresp__pack_to_buffer + (const Mgmt__PoolAddCAResp *message, + ProtobufCBuffer *buffer); +Mgmt__PoolAddCAResp * + mgmt__pool_add_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_add_caresp__free_unpacked + (Mgmt__PoolAddCAResp *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolRemoveCAReq methods */ +void mgmt__pool_remove_careq__init + (Mgmt__PoolRemoveCAReq *message); +size_t mgmt__pool_remove_careq__get_packed_size + (const Mgmt__PoolRemoveCAReq *message); +size_t mgmt__pool_remove_careq__pack + (const Mgmt__PoolRemoveCAReq *message, + uint8_t *out); +size_t mgmt__pool_remove_careq__pack_to_buffer + (const Mgmt__PoolRemoveCAReq *message, + ProtobufCBuffer *buffer); +Mgmt__PoolRemoveCAReq * + mgmt__pool_remove_careq__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_remove_careq__free_unpacked + (Mgmt__PoolRemoveCAReq *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolRemoveCAResp methods */ +void mgmt__pool_remove_caresp__init + (Mgmt__PoolRemoveCAResp *message); +size_t mgmt__pool_remove_caresp__get_packed_size + (const Mgmt__PoolRemoveCAResp *message); +size_t mgmt__pool_remove_caresp__pack + (const Mgmt__PoolRemoveCAResp *message, + uint8_t *out); +size_t mgmt__pool_remove_caresp__pack_to_buffer + (const Mgmt__PoolRemoveCAResp *message, + ProtobufCBuffer *buffer); +Mgmt__PoolRemoveCAResp * + mgmt__pool_remove_caresp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_remove_caresp__free_unpacked + (Mgmt__PoolRemoveCAResp *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolGetCertWatermarksReq methods */ +void mgmt__pool_get_cert_watermarks_req__init + (Mgmt__PoolGetCertWatermarksReq *message); +size_t mgmt__pool_get_cert_watermarks_req__get_packed_size + (const Mgmt__PoolGetCertWatermarksReq *message); +size_t mgmt__pool_get_cert_watermarks_req__pack + (const Mgmt__PoolGetCertWatermarksReq *message, + uint8_t *out); +size_t mgmt__pool_get_cert_watermarks_req__pack_to_buffer + (const Mgmt__PoolGetCertWatermarksReq *message, + ProtobufCBuffer *buffer); +Mgmt__PoolGetCertWatermarksReq * + mgmt__pool_get_cert_watermarks_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_get_cert_watermarks_req__free_unpacked + (Mgmt__PoolGetCertWatermarksReq *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolGetCertWatermarksResp methods */ +void mgmt__pool_get_cert_watermarks_resp__init + (Mgmt__PoolGetCertWatermarksResp *message); +size_t mgmt__pool_get_cert_watermarks_resp__get_packed_size + (const Mgmt__PoolGetCertWatermarksResp *message); +size_t mgmt__pool_get_cert_watermarks_resp__pack + (const Mgmt__PoolGetCertWatermarksResp *message, + uint8_t *out); +size_t mgmt__pool_get_cert_watermarks_resp__pack_to_buffer + (const Mgmt__PoolGetCertWatermarksResp *message, + ProtobufCBuffer *buffer); +Mgmt__PoolGetCertWatermarksResp * + mgmt__pool_get_cert_watermarks_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_get_cert_watermarks_resp__free_unpacked + (Mgmt__PoolGetCertWatermarksResp *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolRevokeClientReq methods */ +void mgmt__pool_revoke_client_req__init + (Mgmt__PoolRevokeClientReq *message); +size_t mgmt__pool_revoke_client_req__get_packed_size + (const Mgmt__PoolRevokeClientReq *message); +size_t mgmt__pool_revoke_client_req__pack + (const Mgmt__PoolRevokeClientReq *message, + uint8_t *out); +size_t mgmt__pool_revoke_client_req__pack_to_buffer + (const Mgmt__PoolRevokeClientReq *message, + ProtobufCBuffer *buffer); +Mgmt__PoolRevokeClientReq * + mgmt__pool_revoke_client_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_revoke_client_req__free_unpacked + (Mgmt__PoolRevokeClientReq *message, + ProtobufCAllocator *allocator); +/* Mgmt__PoolRevokeClientResp methods */ +void mgmt__pool_revoke_client_resp__init + (Mgmt__PoolRevokeClientResp *message); +size_t mgmt__pool_revoke_client_resp__get_packed_size + (const Mgmt__PoolRevokeClientResp *message); +size_t mgmt__pool_revoke_client_resp__pack + (const Mgmt__PoolRevokeClientResp *message, + uint8_t *out); +size_t mgmt__pool_revoke_client_resp__pack_to_buffer + (const Mgmt__PoolRevokeClientResp *message, + ProtobufCBuffer *buffer); +Mgmt__PoolRevokeClientResp * + mgmt__pool_revoke_client_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void mgmt__pool_revoke_client_resp__free_unpacked + (Mgmt__PoolRevokeClientResp *message, + ProtobufCAllocator *allocator); /* --- per-message closures --- */ typedef void (*Mgmt__PoolCreateReq_Closure) @@ -2024,6 +2404,36 @@ typedef void (*Mgmt__PoolRebuildStopReq_Closure) typedef void (*Mgmt__PoolSelfHealEvalReq_Closure) (const Mgmt__PoolSelfHealEvalReq *message, void *closure_data); +typedef void (*Mgmt__PoolGetCAReq_Closure) + (const Mgmt__PoolGetCAReq *message, + void *closure_data); +typedef void (*Mgmt__PoolGetCAResp_Closure) + (const Mgmt__PoolGetCAResp *message, + void *closure_data); +typedef void (*Mgmt__PoolAddCAReq_Closure) + (const Mgmt__PoolAddCAReq *message, + void *closure_data); +typedef void (*Mgmt__PoolAddCAResp_Closure) + (const Mgmt__PoolAddCAResp *message, + void *closure_data); +typedef void (*Mgmt__PoolRemoveCAReq_Closure) + (const Mgmt__PoolRemoveCAReq *message, + void *closure_data); +typedef void (*Mgmt__PoolRemoveCAResp_Closure) + (const Mgmt__PoolRemoveCAResp *message, + void *closure_data); +typedef void (*Mgmt__PoolGetCertWatermarksReq_Closure) + (const Mgmt__PoolGetCertWatermarksReq *message, + void *closure_data); +typedef void (*Mgmt__PoolGetCertWatermarksResp_Closure) + (const Mgmt__PoolGetCertWatermarksResp *message, + void *closure_data); +typedef void (*Mgmt__PoolRevokeClientReq_Closure) + (const Mgmt__PoolRevokeClientReq *message, + void *closure_data); +typedef void (*Mgmt__PoolRevokeClientResp_Closure) + (const Mgmt__PoolRevokeClientResp *message, + void *closure_data); /* --- services --- */ @@ -2071,6 +2481,17 @@ extern const ProtobufCMessageDescriptor mgmt__pool_query_target_resp__descriptor extern const ProtobufCMessageDescriptor mgmt__pool_rebuild_start_req__descriptor; extern const ProtobufCMessageDescriptor mgmt__pool_rebuild_stop_req__descriptor; extern const ProtobufCMessageDescriptor mgmt__pool_self_heal_eval_req__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_get_careq__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_get_caresp__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_add_careq__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_add_caresp__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_remove_careq__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_remove_caresp__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_get_cert_watermarks_req__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_get_cert_watermarks_resp__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_revoke_client_req__descriptor; +extern const ProtobufCEnumDescriptor mgmt__pool_revoke_client_req__evict_mode__descriptor; +extern const ProtobufCMessageDescriptor mgmt__pool_revoke_client_resp__descriptor; PROTOBUF_C__END_DECLS diff --git a/src/mgmt/srv_drpc.c b/src/mgmt/srv_drpc.c index e1cca1f9ea4..850e45fc42a 100644 --- a/src/mgmt/srv_drpc.c +++ b/src/mgmt/srv_drpc.c @@ -1229,6 +1229,24 @@ add_props_to_resp(daos_prop_t *prop, Mgmt__PoolGetPropResp *resp) D_ERROR("pointer-value props not supported\n"); D_GOTO(out, rc = -DER_INVAL); } + } else if (daos_prop_has_byteval(entry)) { + /* Empty leaves byteval = {0, NULL} from + * mgmt__pool_property__init -- the right + * protobuf "empty bytes" wire form. + */ + resp_props[j]->value_case = MGMT__POOL_PROPERTY__VALUE_BYTEVAL; + if (entry->dpe_val_ptr != NULL) { + struct daos_prop_byteval *bv = entry->dpe_val_ptr; + + resp_props[j]->byteval.len = bv->dpb_len; + if (bv->dpb_len > 0) { + D_ALLOC(resp_props[j]->byteval.data, bv->dpb_len); + if (resp_props[j]->byteval.data == NULL) + D_GOTO(out, rc = -DER_NOMEM); + memcpy(resp_props[j]->byteval.data, bv->dpb_data, + bv->dpb_len); + } + } } else { resp_props[j]->numval = entry->dpe_val; resp_props[j]->value_case = diff --git a/src/mgmt/tests/srv_drpc_tests.c b/src/mgmt/tests/srv_drpc_tests.c index 89405711a6e..f173396264f 100644 --- a/src/mgmt/tests/srv_drpc_tests.c +++ b/src/mgmt/tests/srv_drpc_tests.c @@ -980,9 +980,66 @@ test_drpc_pool_set_prop_success(void **state) D_FREE(resp.body.data); } -/* - * TODO (DAOS-18783): Add happy-path byteval test with new property. - */ +static void +test_drpc_pool_set_prop_byteval_success(void **state) +{ + Drpc__Call call = DRPC__CALL__INIT; + Drpc__Response resp = DRPC__RESPONSE__INIT; + Mgmt__PoolSetPropReq req = MGMT__POOL_SET_PROP_REQ__INIT; + uint8_t byte_data[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03}; + + req.id = TEST_UUID; + req.properties = alloc_prop_msg_list(1); + req.n_properties = 1; + + req.properties[0]->number = DAOS_PROP_PO_POOL_CA; + req.properties[0]->byteval.data = byte_data; + req.properties[0]->byteval.len = sizeof(byte_data); + req.properties[0]->value_case = MGMT__POOL_PROPERTY__VALUE_BYTEVAL; + setup_pool_set_prop_drpc_call(&call, &req); + + ds_mgmt_drpc_pool_set_prop(&call, &resp); + + expect_drpc_pool_set_prop_resp_success(&resp, DAOS_PROP_PO_POOL_CA, 0); + + free_prop_msg_list(req.properties, req.n_properties); + D_FREE(call.body.data); + D_FREE(resp.body.data); +} + +static void +test_drpc_pool_set_prop_byteval_oversize(void **state) +{ + Drpc__Call call = DRPC__CALL__INIT; + Drpc__Response resp = DRPC__RESPONSE__INIT; + Mgmt__PoolSetPropReq req = MGMT__POOL_SET_PROP_REQ__INIT; + uint8_t *blob; + size_t oversize = (size_t)DAOS_PROP_BYTEVAL_MAX_LEN + 1; + + /* Real buffer over the cap so protobuf packing reads valid memory; + * cap is enforced in daos_prop_entry_set_byteval, not at the wire. */ + D_ALLOC(blob, oversize); + assert_non_null(blob); + + req.id = TEST_UUID; + req.properties = alloc_prop_msg_list(1); + req.n_properties = 1; + + req.properties[0]->number = DAOS_PROP_PO_POOL_CA; + req.properties[0]->byteval.data = blob; + req.properties[0]->byteval.len = oversize; + req.properties[0]->value_case = MGMT__POOL_PROPERTY__VALUE_BYTEVAL; + setup_pool_set_prop_drpc_call(&call, &req); + + ds_mgmt_drpc_pool_set_prop(&call, &resp); + + expect_drpc_pool_set_prop_resp_with_error(&resp, -DER_INVAL); + + free_prop_msg_list(req.properties, req.n_properties); + D_FREE(call.body.data); + D_FREE(resp.body.data); + D_FREE(blob); +} static void test_drpc_pool_set_prop_byteval_invalid_type(void **state) @@ -1225,6 +1282,43 @@ test_drpc_pool_get_prop_svcl_success(void **state) D_FREE(resp.body.data); } +static void +test_drpc_pool_get_prop_byteval_empty_success(void **state) +{ + Drpc__Call call = DRPC__CALL__INIT; + Drpc__Response resp = DRPC__RESPONSE__INIT; + Mgmt__PoolGetPropReq req = MGMT__POOL_GET_PROP_REQ__INIT; + Mgmt__PoolGetPropResp *get_resp = NULL; + int prop_number = DAOS_PROP_PO_POOL_CA; + + ds_mgmt_pool_get_prop_out = daos_prop_alloc(1); + assert_non_null(ds_mgmt_pool_get_prop_out); + ds_mgmt_pool_get_prop_out->dpp_entries[0].dpe_type = prop_number; + ds_mgmt_pool_get_prop_out->dpp_entries[0].dpe_val_ptr = NULL; + + req.id = TEST_UUID; + req.properties = alloc_prop_msg_list(1); + req.n_properties = 1; + req.properties[0]->number = prop_number; + setup_pool_get_prop_drpc_call(&call, &req); + + ds_mgmt_drpc_pool_get_prop(&call, &resp); + + assert_int_equal(resp.status, DRPC__STATUS__SUCCESS); + get_resp = mgmt__pool_get_prop_resp__unpack(NULL, resp.body.len, resp.body.data); + assert_non_null(get_resp); + assert_int_equal(get_resp->n_properties, 1); + assert_int_equal(get_resp->properties[0]->number, prop_number); + assert_int_equal(get_resp->properties[0]->value_case, MGMT__POOL_PROPERTY__VALUE_BYTEVAL); + assert_int_equal(get_resp->properties[0]->byteval.len, 0); + assert_null(get_resp->properties[0]->byteval.data); + + mgmt__pool_get_prop_resp__free_unpacked(get_resp, NULL); + free_prop_msg_list(req.properties, req.n_properties); + D_FREE(call.body.data); + D_FREE(resp.body.data); +} + static void test_drpc_pool_get_prop_null_svcl(void **state) { @@ -3481,11 +3575,14 @@ main(void) POOL_SET_PROP_TEST(test_drpc_pool_set_prop_invalid_value_type), POOL_SET_PROP_TEST(test_drpc_pool_set_prop_bad_uuid), POOL_SET_PROP_TEST(test_drpc_pool_set_prop_success), + POOL_SET_PROP_TEST(test_drpc_pool_set_prop_byteval_success), + POOL_SET_PROP_TEST(test_drpc_pool_set_prop_byteval_oversize), POOL_SET_PROP_TEST(test_drpc_pool_set_prop_byteval_invalid_type), POOL_GET_PROP_TEST(test_drpc_pool_get_prop_bad_uuid), POOL_GET_PROP_TEST(test_drpc_pool_get_prop_num_success), POOL_GET_PROP_TEST(test_drpc_pool_get_prop_str_success), POOL_GET_PROP_TEST(test_drpc_pool_get_prop_svcl_success), + POOL_GET_PROP_TEST(test_drpc_pool_get_prop_byteval_empty_success), POOL_GET_PROP_TEST(test_drpc_pool_get_prop_null_svcl), EXCLUDE_TEST(test_drpc_exclude_bad_uuid), EXCLUDE_TEST(test_drpc_exclude_mgmt_svc_fails), diff --git a/src/pool/cli.c b/src/pool/cli.c index 70dd17f6380..12174e9ee90 100644 --- a/src/pool/cli.c +++ b/src/pool/cli.c @@ -1,6 +1,6 @@ /* * (C) Copyright 2016-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -246,15 +246,15 @@ dc_pool_init(void) daos_register_key(&dc_pool_module_key); dc_pool_proto_version = 0; - rc = daos_rpc_proto_query(pool_proto_fmt_v6.cpf_base, ver_array, 2, &dc_pool_proto_version); + rc = daos_rpc_proto_query(pool_proto_fmt_v7.cpf_base, ver_array, 2, &dc_pool_proto_version); if (rc) return rc; if (dc_pool_proto_version == DAOS_POOL_VERSION - 1) { - rc = daos_rpc_register(&pool_proto_fmt_v6, POOL_PROTO_CLI_COUNT, NULL, + rc = daos_rpc_register(&pool_proto_fmt_v7, POOL_PROTO_CLI_COUNT, NULL, DAOS_POOL_MODULE); } else if (dc_pool_proto_version == DAOS_POOL_VERSION) { - rc = daos_rpc_register(&pool_proto_fmt_v7, POOL_PROTO_CLI_COUNT, NULL, + rc = daos_rpc_register(&pool_proto_fmt_v8, POOL_PROTO_CLI_COUNT, NULL, DAOS_POOL_MODULE); } else { D_ERROR("%d version pool RPC not supported.\n", dc_pool_proto_version); @@ -277,9 +277,9 @@ dc_pool_fini(void) int rc; if (dc_pool_proto_version == DAOS_POOL_VERSION - 1) { - rc = daos_rpc_unregister(&pool_proto_fmt_v6); - } else if (dc_pool_proto_version == DAOS_POOL_VERSION) { rc = daos_rpc_unregister(&pool_proto_fmt_v7); + } else if (dc_pool_proto_version == DAOS_POOL_VERSION) { + rc = daos_rpc_unregister(&pool_proto_fmt_v8); } else { rc = -DER_PROTO; DL_ERROR(rc, "%d version pool RPC not supported", dc_pool_proto_version); @@ -966,6 +966,17 @@ pool_connect_cp(tse_task_t *task, void *data) pool_connect_in_get_cred(arg->rpc, &credp); pool_connect_in_get_data(arg->rpc, NULL /* flags */, NULL /* bits */, &bulk, NULL /* version */); + { + d_iov_t *certp, *popp, *payloadp; + + pool_connect_in_get_node_cert(arg->rpc, &certp, &popp, &payloadp); + if (certp != NULL) + daos_iov_free(certp); + if (popp != NULL) + daos_iov_free(popp); + if (payloadp != NULL) + daos_iov_free(payloadp); + } crt_req_decref(arg->rpc); map_bulk_destroy(bulk, map_buf); /* Ensure credential memory is wiped clean */ @@ -1064,12 +1075,28 @@ dc_pool_connect_internal(tse_task_t *task, daos_pool_info_t *info, const char *l /** for con_args */ crt_req_addref(rpc); - /** request credentials */ - pool_connect_in_get_cred(rpc, &credp); - rc = dc_sec_request_creds(credp); - if (rc != 0) { - DL_ERROR(rc, "failed to obtain security credential"); - D_GOTO(out_req, rc); + /** request credentials (with per-pool node cert if available) */ + { + d_iov_t node_cert = {0}; + d_iov_t node_cert_pop = {0}; + d_iov_t node_cert_payload = {0}; + + pool_connect_in_get_cred(rpc, &credp); + rc = dc_sec_request_pool_creds(credp, pool->dp_pool, pool->dp_pool_hdl, &node_cert, + &node_cert_pop, &node_cert_payload); + if (rc != 0) { + DL_ERROR(rc, "failed to obtain security credential"); + D_GOTO(out_req, rc); + } + + if (node_cert.iov_len > 0 && rpc_ver_atleast(rpc, POOL_PROTO_VER_WITH_NODE_CERT)) { + pool_connect_in_set_node_cert(rpc, &node_cert, &node_cert_pop, + &node_cert_payload); + } else { + daos_iov_free(&node_cert); + daos_iov_free(&node_cert_pop); + daos_iov_free(&node_cert_payload); + } } rc = map_bulk_create(daos_task2ctx(task), &bulk, &map_buf, pool_buf_nr(pool->dp_map_sz)); @@ -1095,7 +1122,17 @@ dc_pool_connect_internal(tse_task_t *task, daos_pool_info_t *info, const char *l out_bulk: map_bulk_destroy(bulk, map_buf); -out_cred: +out_cred: { + d_iov_t *certp, *popp, *payloadp; + + pool_connect_in_get_node_cert(rpc, &certp, &popp, &payloadp); + if (certp != NULL) + daos_iov_free(certp); + if (popp != NULL) + daos_iov_free(popp); + if (payloadp != NULL) + daos_iov_free(payloadp); +} /* Ensure credential memory is wiped clean */ explicit_bzero(credp->iov_buf, credp->iov_buf_len); daos_iov_free(credp); diff --git a/src/pool/rpc.c b/src/pool/rpc.c index cf11ccbc2a0..e4cbb9c52c7 100644 --- a/src/pool/rpc.c +++ b/src/pool/rpc.c @@ -1,6 +1,6 @@ /** * (C) Copyright 2016-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -82,6 +82,7 @@ crt_proc_struct_pool_op_out(crt_proc_t proc, crt_proc_op_t proc_op, } CRT_RPC_DEFINE(pool_create, DAOS_ISEQ_POOL_CREATE, DAOS_OSEQ_POOL_CREATE) +CRT_RPC_DEFINE(pool_connect_v7, DAOS_ISEQ_POOL_CONNECT_V7, DAOS_OSEQ_POOL_CONNECT) CRT_RPC_DEFINE(pool_connect, DAOS_ISEQ_POOL_CONNECT, DAOS_OSEQ_POOL_CONNECT) CRT_RPC_DEFINE(pool_disconnect, DAOS_ISEQ_POOL_DISCONNECT, DAOS_OSEQ_POOL_DISCONNECT) CRT_RPC_DEFINE(pool_query_v6, DAOS_ISEQ_POOL_QUERY, DAOS_OSEQ_POOL_QUERY_V6) @@ -220,6 +221,8 @@ static struct crt_proto_rpc_format pool_proto_rpc_fmt_v6[] = {POOL_PROTO_CLI_RPC POOL_PROTO_SRV_RPC_LIST(6)}; static struct crt_proto_rpc_format pool_proto_rpc_fmt_v7[] = {POOL_PROTO_CLI_RPC_LIST(7) POOL_PROTO_SRV_RPC_LIST(7)}; +static struct crt_proto_rpc_format pool_proto_rpc_fmt_v8[] = {POOL_PROTO_CLI_RPC_LIST(8) + POOL_PROTO_SRV_RPC_LIST(8)}; #undef X @@ -235,6 +238,12 @@ struct crt_proto_format pool_proto_fmt_v7 = {.cpf_name = "pool", .cpf_prf = pool_proto_rpc_fmt_v7, .cpf_base = DAOS_RPC_OPCODE(0, DAOS_POOL_MODULE, 0)}; +struct crt_proto_format pool_proto_fmt_v8 = {.cpf_name = "pool", + .cpf_ver = 8, + .cpf_count = ARRAY_SIZE(pool_proto_rpc_fmt_v8), + .cpf_prf = pool_proto_rpc_fmt_v8, + .cpf_base = DAOS_RPC_OPCODE(0, DAOS_POOL_MODULE, 0)}; + uint64_t pool_query_bits(daos_pool_info_t *po_info, daos_prop_t *prop) { @@ -339,6 +348,12 @@ pool_query_bits(daos_pool_info_t *po_info, daos_prop_t *prop) case DAOS_PROP_PO_SVC_OPS_ENTRY_AGE: bits |= DAOS_PO_QUERY_PROP_SVC_OPS_ENTRY_AGE; break; + case DAOS_PROP_PO_POOL_CA: + bits |= DAOS_PO_QUERY_PROP_POOL_CA; + break; + case DAOS_PROP_PO_CERT_WATERMARKS: + bits |= DAOS_PO_QUERY_PROP_CERT_WATERMARKS; + break; default: D_ERROR("ignore bad dpt_type %d.\n", entry->dpe_type); break; diff --git a/src/pool/rpc.h b/src/pool/rpc.h index 59567a98892..8564afea408 100644 --- a/src/pool/rpc.h +++ b/src/pool/rpc.h @@ -35,10 +35,12 @@ */ #define POOL_PROTO_VER_WITH_SVC_OP_KEY 6 +#define POOL_PROTO_VER_WITH_NODE_CERT 8 #define POOL_PROTO_CLI_RPC_LIST(ver) \ X(POOL_CREATE, 0, &CQF_pool_create, ds_pool_create_handler, NULL) \ - X(POOL_CONNECT, 0, &CQF_pool_connect, ds_pool_connect_handler, NULL) \ + X(POOL_CONNECT, 0, ver >= 8 ? &CQF_pool_connect : &CQF_pool_connect_v7, \ + ds_pool_connect_handler, NULL) \ X(POOL_DISCONNECT, 0, &CQF_pool_disconnect, ds_pool_disconnect_handler, NULL) \ X(POOL_QUERY, 0, ver >= 7 ? &CQF_pool_query : &CQF_pool_query_v6, \ ver >= 7 ? ds_pool_query_handler : ds_pool_query_handler_v6, NULL) \ @@ -103,6 +105,7 @@ char *dc_pool_op_str(enum pool_operation op); extern struct crt_proto_format pool_proto_fmt_v6; extern struct crt_proto_format pool_proto_fmt_v7; +extern struct crt_proto_format pool_proto_fmt_v8; extern int dc_pool_proto_version; /* clang-format off */ @@ -238,7 +241,7 @@ pool_create_in_set_data(crt_rpc_t *rpc, d_rank_list_t *pri_tgt_ranks, daos_prop_ /* only set on -DER_TRUNC */ \ ((uint32_t) (pco_map_buf_size) CRT_VAR) -#define DAOS_ISEQ_POOL_CONNECT /* input fields */ \ +#define DAOS_ISEQ_POOL_CONNECT_V7 /* input fields (v7) */ \ ((struct pool_op_in) (pci_op) CRT_VAR) \ ((d_iov_t) (pci_cred) CRT_VAR) \ ((uint64_t) (pci_flags) CRT_VAR) \ @@ -246,6 +249,19 @@ pool_create_in_set_data(crt_rpc_t *rpc, d_rank_list_t *pri_tgt_ranks, daos_prop_ ((crt_bulk_t) (pci_map_bulk) CRT_VAR) \ ((uint32_t) (pci_pool_version) CRT_VAR) +#define DAOS_ISEQ_POOL_CONNECT /* input fields (v8+) */ \ + ((struct pool_op_in) (pci_op) CRT_VAR) \ + ((d_iov_t) (pci_cred) CRT_VAR) \ + ((uint64_t) (pci_flags) CRT_VAR) \ + ((uint64_t) (pci_query_bits) CRT_VAR) \ + ((crt_bulk_t) (pci_map_bulk) CRT_VAR) \ + ((uint32_t) (pci_pool_version) CRT_VAR) \ + ((uint32_t) (pci_padding) CRT_VAR) \ + ((d_iov_t) (pci_node_cert) CRT_VAR) \ + ((d_iov_t) (pci_node_cert_pop) CRT_VAR) \ + ((d_iov_t) (pci_node_cert_payload) CRT_VAR) + +CRT_RPC_DECLARE(pool_connect_v7, DAOS_ISEQ_POOL_CONNECT_V7, DAOS_OSEQ_POOL_CONNECT) CRT_RPC_DECLARE(pool_connect, DAOS_ISEQ_POOL_CONNECT, DAOS_OSEQ_POOL_CONNECT) /* clang-format on */ @@ -295,6 +311,36 @@ pool_connect_in_set_data(crt_rpc_t *rpc, uint64_t pci_flags, uint64_t pci_query_ in->pci_pool_version = pci_pool_version; } +static inline void +pool_connect_in_get_node_cert(crt_rpc_t *rpc, d_iov_t **certp, d_iov_t **popp, d_iov_t **payloadp) +{ + struct pool_connect_in *in = crt_req_get(rpc); + + if (rpc_ver_atleast(rpc, POOL_PROTO_VER_WITH_NODE_CERT)) { + *certp = &in->pci_node_cert; + *popp = &in->pci_node_cert_pop; + *payloadp = &in->pci_node_cert_payload; + } else { + *certp = NULL; + *popp = NULL; + *payloadp = NULL; + } +} + +static inline void +pool_connect_in_set_node_cert(crt_rpc_t *rpc, d_iov_t *cert, d_iov_t *pop, d_iov_t *payload) +{ + struct pool_connect_in *in = crt_req_get(rpc); + + D_ASSERT(rpc_ver_atleast(rpc, POOL_PROTO_VER_WITH_NODE_CERT)); + if (cert) + in->pci_node_cert = *cert; + if (pop) + in->pci_node_cert_pop = *pop; + if (payload) + in->pci_node_cert_payload = *payload; +} + /* clang-format off */ #define DAOS_ISEQ_POOL_DISCONNECT /* input fields */ \ diff --git a/src/pool/srv.c b/src/pool/srv.c index 226feeb31c1..6a02c65ca70 100644 --- a/src/pool/srv.c +++ b/src/pool/srv.c @@ -1,6 +1,6 @@ /** * (C) Copyright 2016-2024 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -182,6 +182,9 @@ static struct daos_rpc_handler pool_handlers_v6[] = {POOL_PROTO_CLI_RPC_LIST(6) static struct daos_rpc_handler pool_handlers_v7[] = {POOL_PROTO_CLI_RPC_LIST(7) POOL_PROTO_SRV_RPC_LIST(7)}; +static struct daos_rpc_handler pool_handlers_v8[] = {POOL_PROTO_CLI_RPC_LIST(8) + POOL_PROTO_SRV_RPC_LIST(8)}; + #undef X static void * @@ -242,14 +245,14 @@ struct dss_module pool_module = { .sm_name = "pool", .sm_mod_id = DAOS_POOL_MODULE, .sm_ver = DAOS_POOL_VERSION, - .sm_proto_count = 2, + .sm_proto_count = 3, .sm_init = init, .sm_fini = fini, .sm_setup = setup, .sm_cleanup = cleanup, - .sm_proto_fmt = {&pool_proto_fmt_v6, &pool_proto_fmt_v7}, - .sm_cli_count = {POOL_PROTO_CLI_COUNT, POOL_PROTO_CLI_COUNT}, - .sm_handlers = {pool_handlers_v6, pool_handlers_v7}, + .sm_proto_fmt = {&pool_proto_fmt_v6, &pool_proto_fmt_v7, &pool_proto_fmt_v8}, + .sm_cli_count = {POOL_PROTO_CLI_COUNT, POOL_PROTO_CLI_COUNT, POOL_PROTO_CLI_COUNT}, + .sm_handlers = {pool_handlers_v6, pool_handlers_v7, pool_handlers_v8}, .sm_key = &pool_module_key, .sm_metrics = &pool_metrics, }; diff --git a/src/pool/srv_iv.c b/src/pool/srv_iv.c index 86f29111310..1588c79041a 100644 --- a/src/pool/srv_iv.c +++ b/src/pool/srv_iv.c @@ -1,7 +1,7 @@ /** * (C) Copyright 2017-2024 Intel Corporation. * (C) Copyright 2025 Google LLC - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -93,6 +93,9 @@ pool_iv_prop_l2g(daos_prop_t *prop, struct pool_iv_prop *iv_prop) D_ASSERT(prop->dpp_nr == DAOS_PROP_PO_NUM); for (i = 0; i < DAOS_PROP_PO_NUM; i++) { prop_entry = &prop->dpp_entries[i]; + /* Byteval props are PS-leader-only; never propagated via IV. */ + if (daos_prop_has_byteval(prop_entry)) + continue; switch (prop_entry->dpe_type) { case DAOS_PROP_PO_LABEL: D_ASSERT(strlen(prop_entry->dpe_str) <= @@ -227,6 +230,11 @@ pool_iv_prop_g2l(struct pool_iv_prop *iv_prop, daos_prop_t *prop) for (i = 0; i < DAOS_PROP_PO_NUM; i++) { prop_entry = &prop->dpp_entries[i]; prop_entry->dpe_type = DAOS_PROP_PO_MIN + i + 1; + /* Byteval props are PS-leader-only; never propagated via IV. */ + if (daos_prop_has_byteval(prop_entry)) { + prop_entry->dpe_val_ptr = NULL; + continue; + } switch (prop_entry->dpe_type) { case DAOS_PROP_PO_LABEL: D_ASSERT(strlen(iv_prop->pip_label) <= diff --git a/src/pool/srv_layout.c b/src/pool/srv_layout.c index fefb56d5720..b1ca66a7c35 100644 --- a/src/pool/srv_layout.c +++ b/src/pool/srv_layout.c @@ -1,6 +1,6 @@ /* * (C) Copyright 2017-2023 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -57,6 +57,8 @@ RDB_STRING_KEY(ds_pool_prop_, checkpoint_mode); RDB_STRING_KEY(ds_pool_prop_, checkpoint_freq); RDB_STRING_KEY(ds_pool_prop_, checkpoint_thresh); RDB_STRING_KEY(ds_pool_prop_, reint_mode); +RDB_STRING_KEY(ds_pool_prop_, pool_ca); +RDB_STRING_KEY(ds_pool_prop_, cert_watermarks); /** default properties, should cover all optional pool properties */ struct daos_prop_entry pool_prop_entries_default[DAOS_PROP_PO_NUM] = { @@ -77,7 +79,8 @@ struct daos_prop_entry pool_prop_entries_default[DAOS_PROP_PO_NUM] = { .dpe_val = DAOS_RECLAIM_LAZY, }, { - .dpe_type = DAOS_PROP_PO_ACL, .dpe_val_ptr = NULL, /* generated dynamically */ + .dpe_type = DAOS_PROP_PO_ACL, + .dpe_val_ptr = NULL, /* generated dynamically */ }, { .dpe_type = DAOS_PROP_PO_OWNER, @@ -166,6 +169,14 @@ struct daos_prop_entry pool_prop_entries_default[DAOS_PROP_PO_NUM] = { { .dpe_type = DAOS_PROP_PO_SVC_OPS_ENTRY_AGE, .dpe_val = DAOS_PROP_PO_SVC_OPS_ENTRY_AGE_DEFAULT, + }, + { + .dpe_type = DAOS_PROP_PO_POOL_CA, + .dpe_val_ptr = NULL, + }, + { + .dpe_type = DAOS_PROP_PO_CERT_WATERMARKS, + .dpe_val_ptr = NULL, }}; daos_prop_t pool_prop_default = { diff --git a/src/pool/srv_layout.h b/src/pool/srv_layout.h index 17243d96068..771e6236745 100644 --- a/src/pool/srv_layout.h +++ b/src/pool/srv_layout.h @@ -1,6 +1,6 @@ /* * (C) Copyright 2016-2023 Intel Corporation. - * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -88,6 +88,8 @@ extern d_iov_t ds_pool_prop_svc_ops_age; /* uint32_t */ extern d_iov_t ds_pool_prop_srv_handle; /* uuid_t */ extern d_iov_t ds_pool_prop_srv_cont_handle; /* uuid_t */ extern d_iov_t ds_pool_prop_recov_cont; /* uint32_t */ +extern d_iov_t ds_pool_prop_pool_ca; /* opaque blob */ +extern d_iov_t ds_pool_prop_cert_watermarks; /* opaque blob */ /* Please read the IMPORTANT notes above before adding new keys. */ /* diff --git a/src/pool/srv_pool.c b/src/pool/srv_pool.c index 6ab3e140d9c..39496094a6b 100644 --- a/src/pool/srv_pool.c +++ b/src/pool/srv_pool.c @@ -45,6 +45,7 @@ #define DAOS_POOL_GLOBAL_VERSION_WITH_DATA_THRESH 3 #define DAOS_POOL_GLOBAL_VERSION_WITH_SRV_HDLS 4 #define DAOS_POOL_GLOBAL_VERSION_WITH_OP_VAL_FIX 4 +#define DAOS_POOL_GLOBAL_VERSION_WITH_BYTEVAL_PROPS 5 #define PS_OPS_PER_SEC 4096 @@ -55,12 +56,15 @@ uint32_t ds_pool_get_vos_df_version(uint32_t pool_global_version) { - if (pool_global_version == 4) + switch (pool_global_version) { + case 5: + case 4: return VOS_POOL_DF_2_8; - if (pool_global_version == 3) + case 3: return VOS_POOL_DF_2_6; - else if (pool_global_version == 2) + case 2: return VOS_POOL_DF_2_4; + } return 0; } @@ -391,6 +395,69 @@ ds_pool_svc_rdb_path(const uuid_t pool_uuid) return pool_svc_rdb_path_common(pool_uuid, ""); } +/* Write a byteval pool prop entry to RDB, deleting the key when the value + * is NULL or empty so reads don't have to distinguish "absent" from "empty". + */ +static int +pool_prop_write_byteval(struct rdb_tx *tx, const rdb_path_t *kvs, d_iov_t *key, + const struct daos_prop_entry *entry) +{ + struct daos_prop_byteval *bv = entry->dpe_val_ptr; + d_iov_t value; + int rc; + + if (bv != NULL && bv->dpb_len > 0) { + d_iov_set(&value, bv->dpb_data, bv->dpb_len); + rc = rdb_tx_update(tx, kvs, key, &value); + } else { + rc = rdb_tx_delete(tx, kvs, key); + if (rc == -DER_NONEXIST) + rc = 0; + } + return rc; +} + +/* Read a byteval pool prop entry from RDB into a freshly-allocated + * daos_prop_byteval. Empty or missing keys yield a NULL dpe_val_ptr. + */ +static int +pool_prop_read_byteval(struct rdb_tx *tx, const rdb_path_t *root, d_iov_t *key, + struct daos_prop_entry *entry, uint32_t type) +{ + struct daos_prop_byteval *bv; + d_iov_t value; + int rc; + + entry->dpe_type = type; + entry->dpe_val_ptr = NULL; + d_iov_set(&value, NULL, 0); + rc = rdb_tx_lookup(tx, root, key, &value); + if (rc == -DER_NONEXIST) + return 0; + if (rc != 0) + return rc; + if (value.iov_len == 0) + return 0; + if (value.iov_len > DAOS_PROP_BYTEVAL_MAX_LEN) { + D_ERROR("byteval prop %u in RDB: len %zu exceeds max %u\n", type, value.iov_len, + DAOS_PROP_BYTEVAL_MAX_LEN); + return -DER_INVAL; + } + + D_ALLOC_PTR(bv); + if (bv == NULL) + return -DER_NOMEM; + D_ALLOC(bv->dpb_data, value.iov_len); + if (bv->dpb_data == NULL) { + D_FREE(bv); + return -DER_NOMEM; + } + memcpy(bv->dpb_data, value.iov_buf, value.iov_len); + bv->dpb_len = value.iov_len; + entry->dpe_val_ptr = bv; + return 0; +} + /* copy \a prop to \a prop_def (duplicated default prop) */ static int pool_prop_default_copy(daos_prop_t *prop_def, daos_prop_t *prop) @@ -413,6 +480,12 @@ pool_prop_default_copy(daos_prop_t *prop_def, daos_prop_t *prop) entry_def = daos_prop_entry_get(prop_def, entry->dpe_type); D_ASSERTF(entry_def != NULL, "type %d not found in " "default prop.\n", entry->dpe_type); + if (daos_prop_has_byteval(entry)) { + rc = daos_prop_entry_copy(entry, entry_def); + if (rc) + return rc; + continue; + } switch (entry->dpe_type) { case DAOS_PROP_PO_LABEL: D_FREE(entry_def->dpe_str); @@ -749,6 +822,16 @@ pool_prop_write(struct rdb_tx *tx, const rdb_path_t *kvs, daos_prop_t *prop) if (rc) return rc; break; + case DAOS_PROP_PO_POOL_CA: + rc = pool_prop_write_byteval(tx, kvs, &ds_pool_prop_pool_ca, entry); + if (rc) + return rc; + break; + case DAOS_PROP_PO_CERT_WATERMARKS: + rc = pool_prop_write_byteval(tx, kvs, &ds_pool_prop_cert_watermarks, entry); + if (rc) + return rc; + break; default: D_ERROR("bad dpe_type %d.\n", entry->dpe_type); return -DER_INVAL; @@ -3168,14 +3251,6 @@ pool_prop_read(struct rdb_tx *tx, const struct pool_svc *svc, uint64_t bits, uint32_t idx = 0, nr = 0, val32 = 0, global_ver; int rc; - for (bit = DAOS_PO_QUERY_PROP_BIT_START; - bit <= DAOS_PO_QUERY_PROP_BIT_END; bit++) { - if (bits & (1L << bit)) - nr++; - } - if (nr == 0) - return 0; - /* get pool global version */ d_iov_set(&value, &val32, sizeof(val32)); rc = rdb_tx_lookup(tx, &svc->ps_root, &ds_pool_prop_global_version, @@ -3187,6 +3262,20 @@ pool_prop_read(struct rdb_tx *tx, const struct pool_svc *svc, uint64_t bits, else global_ver = val32; + /* Pre-v5 pools never carry byteval props on the wire; drop the bits so + * the entry walk below skips them and nr is sized accordingly. + */ + if (global_ver < DAOS_POOL_GLOBAL_VERSION_WITH_BYTEVAL_PROPS) + bits &= ~(DAOS_PO_QUERY_PROP_POOL_CA | DAOS_PO_QUERY_PROP_CERT_WATERMARKS); + + for (bit = DAOS_PO_QUERY_PROP_BIT_START; + bit <= DAOS_PO_QUERY_PROP_BIT_END; bit++) { + if (bits & (1L << bit)) + nr++; + } + if (nr == 0) + return 0; + prop = daos_prop_alloc(nr); if (prop == NULL) return -DER_NOMEM; @@ -3636,6 +3725,22 @@ pool_prop_read(struct rdb_tx *tx, const struct pool_svc *svc, uint64_t bits, prop->dpp_entries[idx].dpe_val = val32; idx++; } + if (bits & DAOS_PO_QUERY_PROP_POOL_CA) { + D_ASSERT(idx < nr); + rc = pool_prop_read_byteval(tx, &svc->ps_root, &ds_pool_prop_pool_ca, + &prop->dpp_entries[idx], DAOS_PROP_PO_POOL_CA); + if (rc != 0) + D_GOTO(out_prop, rc); + idx++; + } + if (bits & DAOS_PO_QUERY_PROP_CERT_WATERMARKS) { + D_ASSERT(idx < nr); + rc = pool_prop_read_byteval(tx, &svc->ps_root, &ds_pool_prop_cert_watermarks, + &prop->dpp_entries[idx], DAOS_PROP_PO_CERT_WATERMARKS); + if (rc != 0) + D_GOTO(out_prop, rc); + idx++; + } *prop_out = prop; return 0; @@ -4425,6 +4530,61 @@ pool_connect_handler(crt_rpc_t *rpc, int handler_version) D_ASSERT(obj_ver_entry != NULL); obj_layout_ver = obj_ver_entry->dpe_val; + rc = ds_sec_cred_get_origin(credp, &machine); + if (rc != 0) { + DL_ERROR(rc, DF_UUID ": unable to retrieve origin", DP_UUID(in->pci_op.pi_uuid)); + D_GOTO(out_map_version, rc); + } + + { + struct daos_prop_entry *ca_entry; + struct daos_prop_entry *wm_entry; + + ca_entry = daos_prop_entry_get(prop, DAOS_PROP_PO_POOL_CA); + if (ca_entry != NULL && ca_entry->dpe_val_ptr != NULL) { + struct daos_prop_byteval *ca_bv = ca_entry->dpe_val_ptr; + d_iov_t ca_iov; + d_iov_t wm_iov; + d_iov_t *wm_iov_p = NULL; + d_iov_t *node_cert_p = NULL; + d_iov_t *node_cert_pop_p = NULL; + d_iov_t *node_cert_payload_p = NULL; + + if (!rpc_ver_atleast(rpc, POOL_PROTO_VER_WITH_NODE_CERT)) { + rc = -DER_PROTO; + D_ERROR(DF_UUID ": pool requires node " + "certificate but client protocol " + "version %d does not support it " + "(need >= %d)\n", + DP_UUID(in->pci_op.pi_uuid), opc_get_rpc_ver(rpc->cr_opc), + POOL_PROTO_VER_WITH_NODE_CERT); + D_GOTO(out_map_version, rc); + } + + d_iov_set(&ca_iov, ca_bv->dpb_data, ca_bv->dpb_len); + + pool_connect_in_get_node_cert(rpc, &node_cert_p, &node_cert_pop_p, + &node_cert_payload_p); + + wm_entry = daos_prop_entry_get(prop, DAOS_PROP_PO_CERT_WATERMARKS); + if (wm_entry != NULL && wm_entry->dpe_val_ptr != NULL) { + struct daos_prop_byteval *wm_bv = wm_entry->dpe_val_ptr; + + d_iov_set(&wm_iov, wm_bv->dpb_data, wm_bv->dpb_len); + wm_iov_p = &wm_iov; + } + + rc = ds_sec_validate_node_cert(in->pci_op.pi_uuid, &ca_iov, machine, + wm_iov_p, node_cert_p, node_cert_pop_p, + node_cert_payload_p); + if (rc != 0) { + DL_ERROR(rc, DF_UUID ": node certificate validation failed", + DP_UUID(in->pci_op.pi_uuid)); + D_GOTO(out_map_version, rc); + } + } + } + /* * Security capabilities determine the access control policy on this * pool handle. @@ -4436,13 +4596,6 @@ pool_connect_handler(crt_rpc_t *rpc, int handler_version) D_GOTO(out_map_version, rc); } - rc = ds_sec_cred_get_origin(credp, &machine); - - if (rc != 0) { - DL_ERROR(rc, DF_UUID ": unable to retrieve origin", DP_UUID(in->pci_op.pi_uuid)); - D_GOTO(out_map_version, rc); - } - if (!ds_sec_pool_can_connect(sec_capas)) { rc = -DER_NO_PERM; DL_ERROR(rc, DF_UUID ": permission denied for connect attempt for " DF_X64, @@ -5440,6 +5593,9 @@ pool_query_handler(crt_rpc_t *rpc, int handler_version) for (i = 0; i < prop->dpp_nr; i++) { entry = &prop->dpp_entries[i]; + /* Byteval props are not in the IV bundle. */ + if (daos_prop_has_byteval(entry)) + continue; iv_entry = daos_prop_entry_get(iv_prop, entry->dpe_type); D_ASSERT(iv_entry != NULL); @@ -5809,6 +5965,22 @@ ds_pool_prop_set_handler(crt_rpc_t *rpc) D_GOTO(out_svc, rc = -DER_INVAL); } + if (svc->ps_global_version < DAOS_POOL_GLOBAL_VERSION_WITH_BYTEVAL_PROPS) { + int i; + + for (i = 0; i < prop_in->dpp_nr; i++) { + if (daos_prop_has_byteval(&prop_in->dpp_entries[i])) { + D_ERROR(DF_UUID ": byteval prop %u requires pool version %u " + "(pool is at %u); upgrade the pool first\n", + DP_UUID(in->psi_op.pi_uuid), + prop_in->dpp_entries[i].dpe_type, + DAOS_POOL_GLOBAL_VERSION_WITH_BYTEVAL_PROPS, + svc->ps_global_version); + D_GOTO(out_svc, rc = -DER_NOTSUPPORTED); + } + } + } + rc = rdb_tx_begin(svc->ps_rsvc.s_db, svc->ps_rsvc.s_term, &tx); if (rc != 0) D_GOTO(out_svc, rc); diff --git a/src/proto/mgmt/mgmt.proto b/src/proto/mgmt/mgmt.proto index c49a943cbcd..63235239c1e 100644 --- a/src/proto/mgmt/mgmt.proto +++ b/src/proto/mgmt/mgmt.proto @@ -57,6 +57,16 @@ service MgmtSvc { rpc PoolSetProp(PoolSetPropReq) returns (PoolSetPropResp) {} // Get a DAOS pool property list. rpc PoolGetProp(PoolGetPropReq) returns (PoolGetPropResp) {} + // Read the pool's CA bundle. + rpc PoolGetCA(PoolGetCAReq) returns (PoolGetCAResp) {} + // Append a CA certificate to the pool's CA bundle. + rpc PoolAddCA(PoolAddCAReq) returns (PoolAddCAResp) {} + // Remove one or all CA certificates from the pool's CA bundle. + rpc PoolRemoveCA(PoolRemoveCAReq) returns (PoolRemoveCAResp) {} + // Read the per-CN revocation watermarks for the pool. + rpc PoolGetCertWatermarks(PoolGetCertWatermarksReq) returns (PoolGetCertWatermarksResp) {} + // Advance the cert revocation watermark for a given CN. + rpc PoolRevokeClient(PoolRevokeClientReq) returns (PoolRevokeClientResp) {} // Fetch the Access Control List for a DAOS pool. rpc PoolGetACL(GetACLReq) returns (ACLResp) {} // Overwrite the Access Control List for a DAOS pool with a new one. diff --git a/src/proto/mgmt/pool.proto b/src/proto/mgmt/pool.proto index e994f979545..5266e6ee13c 100644 --- a/src/proto/mgmt/pool.proto +++ b/src/proto/mgmt/pool.proto @@ -380,3 +380,90 @@ message PoolSelfHealEvalReq } // PoolSelfHealEval uses DaosResp + +// PoolGetCAReq fetches the pool's CA bundle. +message PoolGetCAReq +{ + string sys = 1; + string id = 2; + repeated uint32 svc_ranks = 3; +} + +message PoolGetCAResp +{ + int32 status = 1; + bytes ca_bundle = 2; + string pool_uuid = 3; +} + +// PoolAddCAReq appends a CA certificate to the pool's CA bundle. +message PoolAddCAReq +{ + string sys = 1; + string id = 2; + bytes cert_pem = 3; + repeated uint32 svc_ranks = 4; + bool replace = 5; // clear existing bundle before append +} + +message PoolAddCAResp +{ + int32 status = 1; + string pool_uuid = 2; +} + +// PoolRemoveCAReq removes one or all CAs from the pool's CA bundle. +message PoolRemoveCAReq +{ + string sys = 1; + string id = 2; + string fingerprint = 3; // SHA-256 hex of the CA cert to remove + bool all = 4; // remove every CA in the bundle + repeated uint32 svc_ranks = 5; +} + +message PoolRemoveCAResp +{ + int32 status = 1; + int32 certs_removed = 2; + string pool_uuid = 3; +} + +// PoolGetCertWatermarksReq fetches the per-CN revocation watermarks blob. +message PoolGetCertWatermarksReq +{ + string sys = 1; + string id = 2; + repeated uint32 svc_ranks = 3; +} + +message PoolGetCertWatermarksResp +{ + int32 status = 1; + bytes watermarks = 2; // JSON blob, may be empty + string pool_uuid = 3; +} + +// PoolRevokeClientReq advances the pool's revocation watermark for a CN. +message PoolRevokeClientReq +{ + enum EvictMode { + EVICT_DEFAULT = 0; // per-CN for node:, pool-wide for tenant: + EVICT_POOL_WIDE = 1; // always evict all handles on the pool + EVICT_NONE = 2; // advance watermark, leave handles alive + } + string sys = 1; + string id = 2; + string cn = 3; + repeated uint32 svc_ranks = 4; + EvictMode evict_mode = 5; +} + +message PoolRevokeClientResp +{ + int32 status = 1; + string watermark_rfc3339 = 2; // committed watermark in RFC3339 UTC + string pool_uuid = 3; + int32 handles_evicted_count = 4; + string evict_scope = 5; // "machine" | "pool" | "none" +} diff --git a/src/proto/security/auth.proto b/src/proto/security/auth.proto index 1f2a8f84a49..921b780ef68 100644 --- a/src/proto/security/auth.proto +++ b/src/proto/security/auth.proto @@ -1,5 +1,6 @@ // // (C) Copyright 2018-2021 Intel Corporation. +// (C) Copyright 2026 Hewlett Packard Enterprise Development LP // // SPDX-License-Identifier: BSD-2-Clause-Patent // @@ -37,11 +38,17 @@ message Credential { string origin = 3; // the agent that created this credential } -// GetCredResp represents the result of a request to fetch authentication -// credentials. +message GetCredReq { + string pool_id = 1; + bytes handle_uuid = 2; +} + message GetCredResp { - int32 status = 1; // Status of the request - Credential cred = 2; // Caller's authentication credential + int32 status = 1; + Credential cred = 2; + bytes node_cert = 3; + bytes node_cert_pop = 4; + bytes node_cert_payload = 5; } // ValidateCredReq represents a request to verify a set of authentication @@ -56,3 +63,18 @@ message ValidateCredResp { int32 status = 1; // Status of the request Token token = 2; // Validated authentication token from the credential } + +message ValidateNodeCertReq { + bytes pool_ca = 1; + bytes node_cert = 2; + bytes node_cert_pop = 3; + bytes node_cert_payload = 4; + string pool_id = 5; + string machine_name = 6; + bytes cert_watermarks = 7; +} + +message ValidateNodeCertResp { + int32 status = 1; + string detail = 2; +} diff --git a/src/security/auth.pb-c.c b/src/security/auth.pb-c.c index 3bca4487739..8fe53c60685 100644 --- a/src/security/auth.pb-c.c +++ b/src/security/auth.pb-c.c @@ -142,6 +142,51 @@ void auth__credential__free_unpacked assert(message->base.descriptor == &auth__credential__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void auth__get_cred_req__init + (Auth__GetCredReq *message) +{ + static const Auth__GetCredReq init_value = AUTH__GET_CRED_REQ__INIT; + *message = init_value; +} +size_t auth__get_cred_req__get_packed_size + (const Auth__GetCredReq *message) +{ + assert(message->base.descriptor == &auth__get_cred_req__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t auth__get_cred_req__pack + (const Auth__GetCredReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &auth__get_cred_req__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t auth__get_cred_req__pack_to_buffer + (const Auth__GetCredReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &auth__get_cred_req__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Auth__GetCredReq * + auth__get_cred_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Auth__GetCredReq *) + protobuf_c_message_unpack (&auth__get_cred_req__descriptor, + allocator, len, data); +} +void auth__get_cred_req__free_unpacked + (Auth__GetCredReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &auth__get_cred_req__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void auth__get_cred_resp__init (Auth__GetCredResp *message) { @@ -277,6 +322,96 @@ void auth__validate_cred_resp__free_unpacked assert(message->base.descriptor == &auth__validate_cred_resp__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void auth__validate_node_cert_req__init + (Auth__ValidateNodeCertReq *message) +{ + static const Auth__ValidateNodeCertReq init_value = AUTH__VALIDATE_NODE_CERT_REQ__INIT; + *message = init_value; +} +size_t auth__validate_node_cert_req__get_packed_size + (const Auth__ValidateNodeCertReq *message) +{ + assert(message->base.descriptor == &auth__validate_node_cert_req__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t auth__validate_node_cert_req__pack + (const Auth__ValidateNodeCertReq *message, + uint8_t *out) +{ + assert(message->base.descriptor == &auth__validate_node_cert_req__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t auth__validate_node_cert_req__pack_to_buffer + (const Auth__ValidateNodeCertReq *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &auth__validate_node_cert_req__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Auth__ValidateNodeCertReq * + auth__validate_node_cert_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Auth__ValidateNodeCertReq *) + protobuf_c_message_unpack (&auth__validate_node_cert_req__descriptor, + allocator, len, data); +} +void auth__validate_node_cert_req__free_unpacked + (Auth__ValidateNodeCertReq *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &auth__validate_node_cert_req__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void auth__validate_node_cert_resp__init + (Auth__ValidateNodeCertResp *message) +{ + static const Auth__ValidateNodeCertResp init_value = AUTH__VALIDATE_NODE_CERT_RESP__INIT; + *message = init_value; +} +size_t auth__validate_node_cert_resp__get_packed_size + (const Auth__ValidateNodeCertResp *message) +{ + assert(message->base.descriptor == &auth__validate_node_cert_resp__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t auth__validate_node_cert_resp__pack + (const Auth__ValidateNodeCertResp *message, + uint8_t *out) +{ + assert(message->base.descriptor == &auth__validate_node_cert_resp__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t auth__validate_node_cert_resp__pack_to_buffer + (const Auth__ValidateNodeCertResp *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &auth__validate_node_cert_resp__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Auth__ValidateNodeCertResp * + auth__validate_node_cert_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Auth__ValidateNodeCertResp *) + protobuf_c_message_unpack (&auth__validate_node_cert_resp__descriptor, + allocator, len, data); +} +void auth__validate_node_cert_resp__free_unpacked + (Auth__ValidateNodeCertResp *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &auth__validate_node_cert_resp__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} static const ProtobufCFieldDescriptor auth__token__field_descriptors[2] = { { @@ -495,7 +630,58 @@ const ProtobufCMessageDescriptor auth__credential__descriptor = (ProtobufCMessageInit) auth__credential__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor auth__get_cred_resp__field_descriptors[2] = +static const ProtobufCFieldDescriptor auth__get_cred_req__field_descriptors[2] = +{ + { + "pool_id", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Auth__GetCredReq, pool_id), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "handle_uuid", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__GetCredReq, handle_uuid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned auth__get_cred_req__field_indices_by_name[] = { + 1, /* field[1] = handle_uuid */ + 0, /* field[0] = pool_id */ +}; +static const ProtobufCIntRange auth__get_cred_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor auth__get_cred_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "auth.GetCredReq", + "GetCredReq", + "Auth__GetCredReq", + "auth", + sizeof(Auth__GetCredReq), + 2, + auth__get_cred_req__field_descriptors, + auth__get_cred_req__field_indices_by_name, + 1, auth__get_cred_req__number_ranges, + (ProtobufCMessageInit) auth__get_cred_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor auth__get_cred_resp__field_descriptors[5] = { { "status", @@ -521,15 +707,54 @@ static const ProtobufCFieldDescriptor auth__get_cred_resp__field_descriptors[2] 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "node_cert", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__GetCredResp, node_cert), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "node_cert_pop", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__GetCredResp, node_cert_pop), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "node_cert_payload", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__GetCredResp, node_cert_payload), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned auth__get_cred_resp__field_indices_by_name[] = { 1, /* field[1] = cred */ + 2, /* field[2] = node_cert */ + 4, /* field[4] = node_cert_payload */ + 3, /* field[3] = node_cert_pop */ 0, /* field[0] = status */ }; static const ProtobufCIntRange auth__get_cred_resp__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 5 } }; const ProtobufCMessageDescriptor auth__get_cred_resp__descriptor = { @@ -539,7 +764,7 @@ const ProtobufCMessageDescriptor auth__get_cred_resp__descriptor = "Auth__GetCredResp", "auth", sizeof(Auth__GetCredResp), - 2, + 5, auth__get_cred_resp__field_descriptors, auth__get_cred_resp__field_indices_by_name, 1, auth__get_cred_resp__number_ranges, @@ -635,6 +860,173 @@ const ProtobufCMessageDescriptor auth__validate_cred_resp__descriptor = (ProtobufCMessageInit) auth__validate_cred_resp__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor auth__validate_node_cert_req__field_descriptors[7] = +{ + { + "pool_ca", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, pool_ca), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "node_cert", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, node_cert), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "node_cert_pop", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, node_cert_pop), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "node_cert_payload", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, node_cert_payload), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "pool_id", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, pool_id), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "machine_name", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, machine_name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cert_watermarks", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertReq, cert_watermarks), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned auth__validate_node_cert_req__field_indices_by_name[] = { + 6, /* field[6] = cert_watermarks */ + 5, /* field[5] = machine_name */ + 1, /* field[1] = node_cert */ + 3, /* field[3] = node_cert_payload */ + 2, /* field[2] = node_cert_pop */ + 0, /* field[0] = pool_ca */ + 4, /* field[4] = pool_id */ +}; +static const ProtobufCIntRange auth__validate_node_cert_req__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor auth__validate_node_cert_req__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "auth.ValidateNodeCertReq", + "ValidateNodeCertReq", + "Auth__ValidateNodeCertReq", + "auth", + sizeof(Auth__ValidateNodeCertReq), + 7, + auth__validate_node_cert_req__field_descriptors, + auth__validate_node_cert_req__field_indices_by_name, + 1, auth__validate_node_cert_req__number_ranges, + (ProtobufCMessageInit) auth__validate_node_cert_req__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor auth__validate_node_cert_resp__field_descriptors[2] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertResp, status), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "detail", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Auth__ValidateNodeCertResp, detail), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned auth__validate_node_cert_resp__field_indices_by_name[] = { + 1, /* field[1] = detail */ + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange auth__validate_node_cert_resp__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor auth__validate_node_cert_resp__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "auth.ValidateNodeCertResp", + "ValidateNodeCertResp", + "Auth__ValidateNodeCertResp", + "auth", + sizeof(Auth__ValidateNodeCertResp), + 2, + auth__validate_node_cert_resp__field_descriptors, + auth__validate_node_cert_resp__field_indices_by_name, + 1, auth__validate_node_cert_resp__number_ranges, + (ProtobufCMessageInit) auth__validate_node_cert_resp__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCEnumValue auth__flavor__enum_values_by_number[2] = { { "AUTH_NONE", "AUTH__FLAVOR__AUTH_NONE", 0 }, diff --git a/src/security/auth.pb-c.h b/src/security/auth.pb-c.h index 6e1173da6a5..5fda7b2755d 100644 --- a/src/security/auth.pb-c.h +++ b/src/security/auth.pb-c.h @@ -10,7 +10,7 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1003000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif @@ -18,9 +18,12 @@ PROTOBUF_C__BEGIN_DECLS typedef struct _Auth__Token Auth__Token; typedef struct _Auth__Sys Auth__Sys; typedef struct _Auth__Credential Auth__Credential; +typedef struct _Auth__GetCredReq Auth__GetCredReq; typedef struct _Auth__GetCredResp Auth__GetCredResp; typedef struct _Auth__ValidateCredReq Auth__ValidateCredReq; typedef struct _Auth__ValidateCredResp Auth__ValidateCredResp; +typedef struct _Auth__ValidateNodeCertReq Auth__ValidateNodeCertReq; +typedef struct _Auth__ValidateNodeCertResp Auth__ValidateNodeCertResp; /* --- enums --- */ @@ -114,25 +117,29 @@ struct _Auth__Credential , NULL, NULL, (char *)protobuf_c_empty_string } -/* - * GetCredResp represents the result of a request to fetch authentication - * credentials. - */ +struct _Auth__GetCredReq +{ + ProtobufCMessage base; + char *pool_id; + ProtobufCBinaryData handle_uuid; +}; +#define AUTH__GET_CRED_REQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&auth__get_cred_req__descriptor) \ + , (char *)protobuf_c_empty_string, {0,NULL} } + + struct _Auth__GetCredResp { ProtobufCMessage base; - /* - * Status of the request - */ int32_t status; - /* - * Caller's authentication credential - */ Auth__Credential *cred; + ProtobufCBinaryData node_cert; + ProtobufCBinaryData node_cert_pop; + ProtobufCBinaryData node_cert_payload; }; #define AUTH__GET_CRED_RESP__INIT \ { PROTOBUF_C_MESSAGE_INIT (&auth__get_cred_resp__descriptor) \ - , 0, NULL } + , 0, NULL, {0,NULL}, {0,NULL}, {0,NULL} } /* @@ -173,6 +180,33 @@ struct _Auth__ValidateCredResp , 0, NULL } +struct _Auth__ValidateNodeCertReq +{ + ProtobufCMessage base; + ProtobufCBinaryData pool_ca; + ProtobufCBinaryData node_cert; + ProtobufCBinaryData node_cert_pop; + ProtobufCBinaryData node_cert_payload; + char *pool_id; + char *machine_name; + ProtobufCBinaryData cert_watermarks; +}; +#define AUTH__VALIDATE_NODE_CERT_REQ__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&auth__validate_node_cert_req__descriptor) \ + , {0,NULL}, {0,NULL}, {0,NULL}, {0,NULL}, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, {0,NULL} } + + +struct _Auth__ValidateNodeCertResp +{ + ProtobufCMessage base; + int32_t status; + char *detail; +}; +#define AUTH__VALIDATE_NODE_CERT_RESP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&auth__validate_node_cert_resp__descriptor) \ + , 0, (char *)protobuf_c_empty_string } + + /* Auth__Token methods */ void auth__token__init (Auth__Token *message); @@ -230,6 +264,25 @@ Auth__Credential * void auth__credential__free_unpacked (Auth__Credential *message, ProtobufCAllocator *allocator); +/* Auth__GetCredReq methods */ +void auth__get_cred_req__init + (Auth__GetCredReq *message); +size_t auth__get_cred_req__get_packed_size + (const Auth__GetCredReq *message); +size_t auth__get_cred_req__pack + (const Auth__GetCredReq *message, + uint8_t *out); +size_t auth__get_cred_req__pack_to_buffer + (const Auth__GetCredReq *message, + ProtobufCBuffer *buffer); +Auth__GetCredReq * + auth__get_cred_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void auth__get_cred_req__free_unpacked + (Auth__GetCredReq *message, + ProtobufCAllocator *allocator); /* Auth__GetCredResp methods */ void auth__get_cred_resp__init (Auth__GetCredResp *message); @@ -287,6 +340,44 @@ Auth__ValidateCredResp * void auth__validate_cred_resp__free_unpacked (Auth__ValidateCredResp *message, ProtobufCAllocator *allocator); +/* Auth__ValidateNodeCertReq methods */ +void auth__validate_node_cert_req__init + (Auth__ValidateNodeCertReq *message); +size_t auth__validate_node_cert_req__get_packed_size + (const Auth__ValidateNodeCertReq *message); +size_t auth__validate_node_cert_req__pack + (const Auth__ValidateNodeCertReq *message, + uint8_t *out); +size_t auth__validate_node_cert_req__pack_to_buffer + (const Auth__ValidateNodeCertReq *message, + ProtobufCBuffer *buffer); +Auth__ValidateNodeCertReq * + auth__validate_node_cert_req__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void auth__validate_node_cert_req__free_unpacked + (Auth__ValidateNodeCertReq *message, + ProtobufCAllocator *allocator); +/* Auth__ValidateNodeCertResp methods */ +void auth__validate_node_cert_resp__init + (Auth__ValidateNodeCertResp *message); +size_t auth__validate_node_cert_resp__get_packed_size + (const Auth__ValidateNodeCertResp *message); +size_t auth__validate_node_cert_resp__pack + (const Auth__ValidateNodeCertResp *message, + uint8_t *out); +size_t auth__validate_node_cert_resp__pack_to_buffer + (const Auth__ValidateNodeCertResp *message, + ProtobufCBuffer *buffer); +Auth__ValidateNodeCertResp * + auth__validate_node_cert_resp__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void auth__validate_node_cert_resp__free_unpacked + (Auth__ValidateNodeCertResp *message, + ProtobufCAllocator *allocator); /* --- per-message closures --- */ typedef void (*Auth__Token_Closure) @@ -298,6 +389,9 @@ typedef void (*Auth__Sys_Closure) typedef void (*Auth__Credential_Closure) (const Auth__Credential *message, void *closure_data); +typedef void (*Auth__GetCredReq_Closure) + (const Auth__GetCredReq *message, + void *closure_data); typedef void (*Auth__GetCredResp_Closure) (const Auth__GetCredResp *message, void *closure_data); @@ -307,6 +401,12 @@ typedef void (*Auth__ValidateCredReq_Closure) typedef void (*Auth__ValidateCredResp_Closure) (const Auth__ValidateCredResp *message, void *closure_data); +typedef void (*Auth__ValidateNodeCertReq_Closure) + (const Auth__ValidateNodeCertReq *message, + void *closure_data); +typedef void (*Auth__ValidateNodeCertResp_Closure) + (const Auth__ValidateNodeCertResp *message, + void *closure_data); /* --- services --- */ @@ -317,9 +417,12 @@ extern const ProtobufCEnumDescriptor auth__flavor__descriptor; extern const ProtobufCMessageDescriptor auth__token__descriptor; extern const ProtobufCMessageDescriptor auth__sys__descriptor; extern const ProtobufCMessageDescriptor auth__credential__descriptor; +extern const ProtobufCMessageDescriptor auth__get_cred_req__descriptor; extern const ProtobufCMessageDescriptor auth__get_cred_resp__descriptor; extern const ProtobufCMessageDescriptor auth__validate_cred_req__descriptor; extern const ProtobufCMessageDescriptor auth__validate_cred_resp__descriptor; +extern const ProtobufCMessageDescriptor auth__validate_node_cert_req__descriptor; +extern const ProtobufCMessageDescriptor auth__validate_node_cert_resp__descriptor; PROTOBUF_C__END_DECLS diff --git a/src/security/cli_security.c b/src/security/cli_security.c index 6aca0e0565d..38242eb1762 100644 --- a/src/security/cli_security.c +++ b/src/security/cli_security.c @@ -1,5 +1,6 @@ /* * (C) Copyright 2018-2023 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -21,10 +22,14 @@ #include "acl.h" /* Prototypes for static helper functions */ -static int request_credentials_via_drpc(Drpc__Response **response); -static int process_credential_response(Drpc__Response *response, - d_iov_t *creds); -static int get_cred_from_response(Drpc__Response *response, d_iov_t *cred); +static int +request_credentials_via_drpc(uuid_t pool_uuid, uuid_t handle_uuid, Drpc__Response **response); +static int +process_credential_response(Drpc__Response *response, d_iov_t *creds, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload); +static int +get_cred_from_response(Drpc__Response *response, d_iov_t *cred, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload); int dc_sec_request_creds(d_iov_t *creds) @@ -32,28 +37,53 @@ dc_sec_request_creds(d_iov_t *creds) Drpc__Response *response = NULL; int rc; - if (creds == NULL) { + if (creds == NULL) return -DER_INVAL; + + rc = request_credentials_via_drpc(NULL, NULL, &response); + if (rc != DER_SUCCESS) { + drpc_response_free(response); + return rc; } - rc = request_credentials_via_drpc(&response); + rc = process_credential_response(response, creds, NULL, NULL, NULL); + + drpc_response_free(response); + return rc; +} + +int +dc_sec_request_pool_creds(d_iov_t *creds, uuid_t pool_uuid, uuid_t handle_uuid, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload) +{ + Drpc__Response *response = NULL; + int rc; + + if (creds == NULL) + return -DER_INVAL; + + rc = request_credentials_via_drpc(pool_uuid, handle_uuid, &response); if (rc != DER_SUCCESS) { drpc_response_free(response); return rc; } - rc = process_credential_response(response, creds); + rc = process_credential_response(response, creds, node_cert, node_cert_pop, + node_cert_payload); drpc_response_free(response); return rc; } static int -request_credentials_via_drpc(Drpc__Response **response) +request_credentials_via_drpc(uuid_t pool_uuid, uuid_t handle_uuid, Drpc__Response **response) { - Drpc__Call *request; - struct drpc *agent_socket; - int rc; + Drpc__Call *request; + struct drpc *agent_socket; + Auth__GetCredReq req = AUTH__GET_CRED_REQ__INIT; + char uuid_str[DAOS_UUID_STR_SIZE]; + size_t req_len; + int rc; if (dc_agent_sockpath == NULL) { D_ERROR("DAOS Socket Path is Uninitialized\n"); @@ -76,6 +106,25 @@ request_credentials_via_drpc(Drpc__Response **response) return rc; } + if (pool_uuid != NULL) { + uuid_unparse_lower(pool_uuid, uuid_str); + req.pool_id = uuid_str; + } + if (handle_uuid != NULL) { + req.handle_uuid.data = (uint8_t *)handle_uuid; + req.handle_uuid.len = sizeof(uuid_t); + } + + req_len = auth__get_cred_req__get_packed_size(&req); + D_ALLOC(request->body.data, req_len); + if (request->body.data == NULL) { + drpc_call_free(request); + drpc_close(agent_socket); + return -DER_NOMEM; + } + request->body.len = req_len; + auth__get_cred_req__pack(&req, request->body.data); + rc = drpc_call(agent_socket, R_SYNC, request, response); drpc_close(agent_socket); @@ -84,7 +133,8 @@ request_credentials_via_drpc(Drpc__Response **response) } static int -process_credential_response(Drpc__Response *response, d_iov_t *creds) +process_credential_response(Drpc__Response *response, d_iov_t *creds, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload) { if (response == NULL) { D_ERROR("Response was null\n"); @@ -98,7 +148,7 @@ process_credential_response(Drpc__Response *response, d_iov_t *creds) return -DER_MISC; } - return get_cred_from_response(response, creds); + return get_cred_from_response(response, creds, node_cert, node_cert_pop, node_cert_payload); } static int @@ -119,7 +169,8 @@ auth_cred_to_iov(Auth__Credential *cred, d_iov_t *iov) } static int -get_cred_from_response(Drpc__Response *response, d_iov_t *cred) +get_cred_from_response(Drpc__Response *response, d_iov_t *cred, d_iov_t *node_cert, + d_iov_t *node_cert_pop, d_iov_t *node_cert_payload) { struct drpc_alloc alloc = PROTO_ALLOCATOR_INIT(alloc); int rc = 0; @@ -158,10 +209,51 @@ get_cred_from_response(Drpc__Response *response, d_iov_t *cred) } rc = auth_cred_to_iov(cred_resp->cred, cred); + if (rc != 0) + D_GOTO(out, rc); + + if (node_cert != NULL && cred_resp->node_cert.len > 0) { + D_ALLOC(node_cert->iov_buf, cred_resp->node_cert.len); + if (node_cert->iov_buf == NULL) + D_GOTO(out_partial, rc = -DER_NOMEM); + memcpy(node_cert->iov_buf, cred_resp->node_cert.data, cred_resp->node_cert.len); + node_cert->iov_buf_len = cred_resp->node_cert.len; + node_cert->iov_len = cred_resp->node_cert.len; + } + + if (node_cert_pop != NULL && cred_resp->node_cert_pop.len > 0) { + D_ALLOC(node_cert_pop->iov_buf, cred_resp->node_cert_pop.len); + if (node_cert_pop->iov_buf == NULL) + D_GOTO(out_partial, rc = -DER_NOMEM); + memcpy(node_cert_pop->iov_buf, cred_resp->node_cert_pop.data, + cred_resp->node_cert_pop.len); + node_cert_pop->iov_buf_len = cred_resp->node_cert_pop.len; + node_cert_pop->iov_len = cred_resp->node_cert_pop.len; + } + + if (node_cert_payload != NULL && cred_resp->node_cert_payload.len > 0) { + D_ALLOC(node_cert_payload->iov_buf, cred_resp->node_cert_payload.len); + if (node_cert_payload->iov_buf == NULL) + D_GOTO(out_partial, rc = -DER_NOMEM); + memcpy(node_cert_payload->iov_buf, cred_resp->node_cert_payload.data, + cred_resp->node_cert_payload.len); + node_cert_payload->iov_buf_len = cred_resp->node_cert_payload.len; + node_cert_payload->iov_len = cred_resp->node_cert_payload.len; + } /* If present clear out the verifier (the secret part) */ verifier = cred_resp->cred->verifier; explicit_bzero(verifier->data.data, verifier->data.len); + goto out; + +out_partial: + daos_iov_free(cred); + if (node_cert != NULL) + daos_iov_free(node_cert); + if (node_cert_pop != NULL) + daos_iov_free(node_cert_pop); + if (node_cert_payload != NULL) + daos_iov_free(node_cert_payload); out: auth__get_cred_resp__free_unpacked(cred_resp, &alloc.alloc); return rc; diff --git a/src/security/srv_acl.c b/src/security/srv_acl.c index 8f05216e971..5b216d38b79 100644 --- a/src/security/srv_acl.c +++ b/src/security/srv_acl.c @@ -1,5 +1,6 @@ /* * (C) Copyright 2019-2024 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -279,6 +280,112 @@ ds_sec_validate_credentials(d_iov_t *creds, Auth__Token **token) return rc; } +int +ds_sec_validate_node_cert(uuid_t pool_uuid, d_iov_t *pool_ca, const char *machine, + d_iov_t *cert_watermarks, d_iov_t *node_cert, d_iov_t *node_cert_pop, + d_iov_t *node_cert_payload) +{ + struct drpc_alloc alloc = PROTO_ALLOCATOR_INIT(alloc); + Auth__ValidateNodeCertReq req = AUTH__VALIDATE_NODE_CERT_REQ__INIT; + Auth__ValidateNodeCertResp *resp = NULL; + struct drpc *server_socket; + Drpc__Call *request; + Drpc__Response *response = NULL; + char pool_id_str[DAOS_UUID_STR_SIZE]; + uint8_t *body; + size_t len; + int rc; + + /* Short-circuit before the dRPC for the common rejection case. */ + if (node_cert == NULL || node_cert->iov_len == 0) + return -DER_NO_CERT; + + rc = drpc_connect(ds_sec_server_socket_path, &server_socket); + if (rc != DER_SUCCESS) { + D_ERROR("Couldn't connect to daos_server socket: " DF_RC "\n", DP_RC(rc)); + return rc; + } + + rc = drpc_call_create(server_socket, DRPC_MODULE_SEC, DRPC_METHOD_SEC_VALIDATE_NODE_CERT, + &request); + if (rc != DER_SUCCESS) { + drpc_close(server_socket); + return rc; + } + + uuid_unparse_lower(pool_uuid, pool_id_str); + req.pool_id = pool_id_str; + req.pool_ca.data = pool_ca->iov_buf; + req.pool_ca.len = pool_ca->iov_len; + req.node_cert.data = node_cert->iov_buf; + req.node_cert.len = node_cert->iov_len; + req.node_cert_pop.data = node_cert_pop->iov_buf; + req.node_cert_pop.len = node_cert_pop->iov_len; + + req.node_cert_payload.data = node_cert_payload->iov_buf; + req.node_cert_payload.len = node_cert_payload->iov_len; + if (machine != NULL) + req.machine_name = (char *)machine; + + if (cert_watermarks != NULL && cert_watermarks->iov_len > 0) { + req.cert_watermarks.data = cert_watermarks->iov_buf; + req.cert_watermarks.len = cert_watermarks->iov_len; + } + + len = auth__validate_node_cert_req__get_packed_size(&req); + D_ALLOC(body, len); + if (body == NULL) { + rc = -DER_NOMEM; + goto out_request; + } + auth__validate_node_cert_req__pack(&req, body); + request->body.len = len; + request->body.data = body; + + rc = drpc_call(server_socket, R_SYNC, request, &response); + + drpc_close(server_socket); + drpc_call_free(request); + + if (rc != DER_SUCCESS) + return rc; + + if (response == NULL) { + D_ERROR("Node cert validation response was NULL\n"); + return -DER_NOREPLY; + } + + if (response->status != DRPC__STATUS__SUCCESS) { + D_ERROR("Node cert validation dRPC error: %d\n", response->status); + drpc_response_free(response); + return -DER_MISC; + } + + resp = auth__validate_node_cert_resp__unpack(&alloc.alloc, response->body.len, + response->body.data); + if (alloc.oom || resp == NULL) { + drpc_response_free(response); + return -DER_NOMEM; + } + + if (resp->status != 0) { + rc = resp->status; + if (resp->detail != NULL && resp->detail[0] != '\0') + D_ERROR("Node cert validation failed: status=%d (%s)\n", rc, resp->detail); + else + D_ERROR("Node cert validation failed: status=%d\n", rc); + } + + auth__validate_node_cert_resp__free_unpacked(resp, &alloc.alloc); + drpc_response_free(response); + return rc; + +out_request: + drpc_call_free(request); + drpc_close(server_socket); + return rc; +} + static uint64_t pool_capas_from_perms(uint64_t perms, bool is_owner) { diff --git a/src/security/tests/SConscript b/src/security/tests/SConscript index 8c363f42ff3..3698c4f701e 100644 --- a/src/security/tests/SConscript +++ b/src/security/tests/SConscript @@ -1,4 +1,9 @@ """Build daos security tests""" +# +# (C) Copyright 2026 Hewlett Packard Enterprise Development LP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# def scons(): @@ -10,11 +15,11 @@ def scons(): # Isolated unit tests denv.d_test_program('cli_security_tests', source=['cli_security_tests.c', util, dc_security_tgts, mocks], - LIBS=['cmocka', 'protobuf-c', 'daos_common', 'gurt']) + LIBS=['cmocka', 'protobuf-c', 'daos_common', 'gurt', 'uuid']) denv.d_test_program('srv_acl_tests', source=['srv_acl_tests.c', util, acl_tgts, mocks], - LIBS=['cmocka', 'protobuf-c', 'daos_common', 'gurt']) + LIBS=['cmocka', 'protobuf-c', 'daos_common', 'gurt', 'uuid']) if __name__ == "SCons.Script": diff --git a/src/tests/ftest/security/node_cert_handle_holder.py b/src/tests/ftest/security/node_cert_handle_holder.py new file mode 100644 index 00000000000..dee48873b3d --- /dev/null +++ b/src/tests/ftest/security/node_cert_handle_holder.py @@ -0,0 +1,91 @@ +""" + (C) Copyright 2026 Hewlett Packard Enterprise Development LP + + SPDX-License-Identifier: BSD-2-Clause-Patent + + Open a pool handle and keep it live until SIGTERM. The PoolNodeAuthRevoke + eviction tests use this to plant a real, machine-bound handle on a + remote client host so that `dmg pool revoke-client` has something to + evict and the assertions on handles_evicted/evict_scope are meaningful. + + After opening the handle, the holder loops calling pool_query against + that same handle every few seconds. If the handle has been evicted + server-side, pool_query fails and the holder exits non-zero — which the + test interprets as "the existing handle was torn down". The + --no-evict test reads "process still alive after revoke" as "the existing + handle survived". + + Usage: + python3 node_cert_handle_holder.py LIB64_DIR POOL_UUID PIDFILE READYFILE [GROUP] + + LIB64_DIR is the install lib64 directory (e.g. /opt/daos/install/lib64 + for source builds, /usr/lib64 for RPMs) — the caller passes the install + prefix because the holder script can't infer it. +""" +import os +import signal +import sys +import time + +from pydaos.raw import DaosApiError, DaosContext, DaosPool + +_HEARTBEAT_INTERVAL_SEC = 2 + + +def _terminate(_signum, _frame): + # Exit without disconnecting: the whole point is that the handle is + # still live when revoke runs, so the server has something to evict. + sys.exit(0) + + +def main(): + """Open a pool handle on the calling host and hold it open until signaled.""" + if len(sys.argv) < 5: + print("usage: node_cert_handle_holder.py LIB64_DIR POOL_UUID " + "PIDFILE READYFILE [GROUP]", file=sys.stderr) + sys.exit(2) + + lib64_dir = sys.argv[1] + pool_uuid = sys.argv[2] + pidfile = sys.argv[3] + readyfile = sys.argv[4] + group = sys.argv[5] if len(sys.argv) > 5 else "daos_server" + + # Order matters: + # 1. pidfile FIRST so the test can always find this process for + # cleanup, even if any subsequent step fails. + # 2. Signal handlers BEFORE pool.connect() so SIGTERM during the + # connect window can't leave a half-opened handle behind. + # 3. pool.connect() — the work that needs cleanup. + # 4. readyfile LAST — the canary the test polls for; signals that + # the handle is open and the holder is in its heartbeat loop. + with open(pidfile, "w", encoding="utf-8") as fh: + fh.write(f"{os.getpid()}\n") + + signal.signal(signal.SIGTERM, _terminate) + signal.signal(signal.SIGINT, _terminate) + + context = DaosContext(lib64_dir) + pool = DaosPool(context) + pool.set_uuid_str(pool_uuid) + pool.set_group(group.encode()) + # DAOS_PC_RO = 1; RO is enough for revoke to see a live handle. + pool.connect(1) + + with open(readyfile, "w", encoding="utf-8") as fh: + fh.write("ready\n") + + # Heartbeat loop: an op on the existing handle. If the server has + # evicted the handle (revoke without --no-evict), pool_query will + # fail and we exit non-zero so the test can see the canary stop. + while True: + try: + pool.pool_query() + except DaosApiError as exc: + print(f"pool_query failed: {exc}", file=sys.stderr) + sys.exit(3) + time.sleep(_HEARTBEAT_INTERVAL_SEC) + + +if __name__ == "__main__": + main() diff --git a/src/tests/ftest/security/pool_node_auth.py b/src/tests/ftest/security/pool_node_auth.py new file mode 100644 index 00000000000..0e601ce939f --- /dev/null +++ b/src/tests/ftest/security/pool_node_auth.py @@ -0,0 +1,219 @@ +""" + (C) Copyright 2026 Hewlett Packard Enterprise Development LP + + SPDX-License-Identifier: BSD-2-Clause-Patent +""" +import os + +from node_auth_test_base import NodeAuthTestBase + + +class PoolNodeAuthTest(NodeAuthTestBase): + """Tests for per-pool node certificate authentication. + + :avocado: recursive + """ + + def test_pool_cert_lifecycle(self): + """Set-cert generate, get-cert, add-client, connect, delete-cert --all. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_pool_cert_lifecycle + """ + self.setup_pool_with_cert_auth() + + info = self.get_dmg_command().pool_get_cert(pool=str(self.pool.uuid)) + certs = info["response"]["certificates"] + if len(certs) != 1: + self.fail(f"expected 1 cert after set-cert, got {len(certs)}") + + host = self.hostlist_clients[0:1] + cert, key = self.add_client_cert(node=str(host[0])) + self.install_node_cert(cert, key, host) + self.expect_connect_succeeds(host) + + self.get_dmg_command().pool_delete_cert(pool=str(self.pool.uuid), delete_all=True) + # Bundle cleared; the agent's installed cert is harmless now. + self.remove_node_cert(host) + self.expect_connect_succeeds(host) + + def test_pool_cert_import_mode(self): + """Import a pre-existing CA via dmg pool set-cert --cert. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_pool_cert_import_mode + """ + self.setup_pool_with_cert_auth() + existing_ca = self.pool_ca_cert + + # Fresh pool, import the same CA. + self.add_pool(connect=False) + self.get_dmg_command().pool_set_cert( + pool=str(self.pool.uuid), cert=existing_ca) + info = self.get_dmg_command().pool_get_cert(pool=str(self.pool.uuid)) + if len(info["response"]["certificates"]) != 1: + self.fail("import-mode set-cert did not install the bundle") + + def test_set_cert_requires_explicit_intent(self): + """Re-running set-cert on a pool with CAs requires --replace or --append. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_set_cert_requires_explicit_intent + """ + self.setup_pool_with_cert_auth() + existing_ca = self.pool_ca_cert + try: + self.get_dmg_command().pool_set_cert( + pool=str(self.pool.uuid), cert=existing_ca) + except Exception as e: # pylint: disable=broad-except + if "specify --replace or --append" not in str(e): + self.fail(f"unexpected error: {e}") + return + self.fail("set-cert without --replace/--append should have failed") + + def test_set_cert_replace_clears_bundle(self): + """--replace clears the bundle so only the new CA remains. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_set_cert_replace_clears_bundle + """ + self.setup_pool_with_cert_auth() + original_fp = self.get_dmg_command().pool_get_cert( + pool=str(self.pool.uuid))["response"]["certificates"][0]["fingerprint"] + + # Generate a new CA on a sibling pool, then --replace into the original. + sibling_dir = os.path.join(self.cert_workdir, "sibling") + os.makedirs(sibling_dir, exist_ok=True) + original = self.pool + self.add_pool(connect=False) + sibling = self.pool + sibling_uuid_lc = str(sibling.uuid).lower() + self.get_dmg_command().pool_set_cert( + pool=str(sibling.uuid), + daos_ca_key=self._daos_ca_key_path(), + output=sibling_dir) + sibling_ca = os.path.join(sibling_dir, f"{sibling_uuid_lc}_ca.crt") + + self.pool = original + self.get_dmg_command().pool_set_cert( + pool=str(self.pool.uuid), cert=sibling_ca, replace=True) + + certs = self.get_dmg_command().pool_get_cert( + pool=str(self.pool.uuid))["response"]["certificates"] + if len(certs) != 1: + self.fail(f"expected 1 cert after --replace, got {len(certs)}") + if certs[0]["fingerprint"] == original_fp: + self.fail("original CA was not replaced") + + def test_pool_cert_rejections(self): + """Negative cases: no cert, wrong CA, CN mismatch, cross-pool. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_pool_cert_rejections + """ + self.setup_pool_with_cert_auth() + original_pool = self.pool + host = self.hostlist_clients[0:1] + + # No cert installed. + self.expect_connect_rejected(host) + + # CN=node: presented from the right host. + cert, key = self.add_client_cert(node="nonexistent-host-name") + self.install_node_cert(cert, key, host) + self.expect_connect_rejected(host) + self.remove_node_cert(host) + + # Cert signed by an unrelated CA. + other_dir = os.path.join(self.cert_workdir, "other") + os.makedirs(other_dir, exist_ok=True) + self.add_pool(connect=False) + other_pool = self.pool + other_uuid_lc = str(other_pool.uuid).lower() + self.get_dmg_command().pool_set_cert( + pool=str(other_pool.uuid), + daos_ca_key=self._daos_ca_key_path(), + output=other_dir) + unrelated_ca_key = os.path.join(other_dir, f"{other_uuid_lc}_ca.key") + self.get_dmg_command().pool_add_client( + pool=str(other_pool.uuid), + pool_ca_key=unrelated_ca_key, + output=other_dir, node=str(host[0])) + unrelated_cert = os.path.join(other_dir, str(host[0]), + f"{other_uuid_lc}.crt") + unrelated_key = os.path.join(other_dir, str(host[0]), + f"{other_uuid_lc}.key") + # Install the unrelated cert under the original pool's uuid path. + self.pool = original_pool + self.install_node_cert(unrelated_cert, unrelated_key, host) + self.expect_connect_rejected(host) + + def test_pool_cert_multi_ca(self): + """Bundle of 2 CAs; delete one by fingerprint; remaining still works. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthTest,test_pool_cert_multi_ca + """ + self.setup_pool_with_cert_auth() + original_pool = self.pool + host = self.hostlist_clients[0:1] + + # Add a second CA to the bundle. We reuse set-cert (generate mode) + # against a second pool to get a second CA cert+key, then import + # that CA into the first pool's bundle via dmg pool set-cert --cert. + # In real deployments the operator's external CA would be the source. + second_dir = os.path.join(self.cert_workdir, "second") + os.makedirs(second_dir, exist_ok=True) + self.add_pool(connect=False) + second_pool = self.pool + second_uuid_lc = str(second_pool.uuid).lower() + self.get_dmg_command().pool_set_cert( + pool=str(second_pool.uuid), + daos_ca_key=self._daos_ca_key_path(), + output=second_dir) + second_ca_cert = os.path.join(second_dir, f"{second_uuid_lc}_ca.crt") + second_ca_key = os.path.join(second_dir, f"{second_uuid_lc}_ca.key") + + self.pool = original_pool + self.get_dmg_command().pool_set_cert( + pool=str(self.pool.uuid), cert=second_ca_cert, append=True) + + info = self.get_dmg_command().pool_get_cert(pool=str(self.pool.uuid)) + certs = info["response"]["certificates"] + if len(certs) != 2: + self.fail(f"expected 2 certs after second set-cert, got {len(certs)}") + first_fp = certs[0]["fingerprint"] + second_fp = certs[1]["fingerprint"] + + # A client signed by the second CA must connect. + self.get_dmg_command().pool_add_client( + pool=str(self.pool.uuid), + pool_ca_key=second_ca_key, + output=second_dir, node=str(host[0])) + uuid_lc = str(self.pool.uuid).lower() + cert = os.path.join(second_dir, str(host[0]), f"{uuid_lc}.crt") + key = os.path.join(second_dir, str(host[0]), f"{uuid_lc}.key") + self.install_node_cert(cert, key, host) + self.expect_connect_succeeds(host) + + # Remove the second CA. The installed client cert is signed by the + # now-removed CA and must be rejected. + self.get_dmg_command().pool_delete_cert( + pool=str(self.pool.uuid), fingerprint=second_fp) + info = self.get_dmg_command().pool_get_cert(pool=str(self.pool.uuid)) + remaining = info["response"]["certificates"] + if len(remaining) != 1 or remaining[0]["fingerprint"] != first_fp: + self.fail("delete-cert --fingerprint did not remove the right CA") + self.expect_connect_rejected(host) diff --git a/src/tests/ftest/security/pool_node_auth.yaml b/src/tests/ftest/security/pool_node_auth.yaml new file mode 100644 index 00000000000..bdc2ca6267c --- /dev/null +++ b/src/tests/ftest/security/pool_node_auth.yaml @@ -0,0 +1,34 @@ +# (C) Copyright 2026 Hewlett Packard Enterprise Development LP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +hosts: + test_servers: 3 + test_clients: 1 +timeout: 1200 +server_config: + name: daos_server + port: 10001 + engines_per_host: 1 + engines: + 0: + targets: 4 + nr_xs_helpers: 0 + storage: + 0: + class: ram + scm_mount: /mnt/daos + scm_size: 4 + system_ram_reserved: 1 +pool: + scm_size: 134217728 + svc_redun_fac: 1 + transport_config: + allow_insecure: False +agent_config: + transport_config: + allow_insecure: False +dmg: + transport_config: + allow_insecure: False +container: + control_method: daos diff --git a/src/tests/ftest/security/pool_node_auth_revoke.py b/src/tests/ftest/security/pool_node_auth_revoke.py new file mode 100644 index 00000000000..0821c23b93a --- /dev/null +++ b/src/tests/ftest/security/pool_node_auth_revoke.py @@ -0,0 +1,182 @@ +""" + (C) Copyright 2026 Hewlett Packard Enterprise Development LP + + SPDX-License-Identifier: BSD-2-Clause-Patent +""" +import time + +from node_auth_test_base import NodeAuthTestBase + + +class PoolNodeAuthRevokeTest(NodeAuthTestBase): + """Revocation tests: a revoked client must be evicted and cannot reconnect. + + :avocado: recursive + """ + + def test_revoke_blocks_reconnect(self): + """After revoke, a fresh connect with the old cert is rejected. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_revoke_blocks_reconnect + """ + self.setup_pool_with_cert_auth() + host = self.hostlist_clients[0:1] + cn = str(host[0]) + cert, key = self.add_client_cert(node=cn) + self.install_node_cert(cert, key, host) + self.expect_connect_succeeds(host) + + self.revoke_client(node=cn) + revs = self.get_dmg_command().pool_list_revocations(pool=str(self.pool.uuid)) + if f"node:{cn}" not in revs["response"]["revocations"]: + self.fail("list-revocations missing the revoked CN") + + # The agent's cached old cert must not authenticate. + self.expect_connect_rejected(host) + + def test_revoke_replacement_works(self): + """After revoke, the replacement cert must authenticate. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_revoke_replacement_works + """ + self.setup_pool_with_cert_auth() + host = self.hostlist_clients[0:1] + cn = str(host[0]) + cert, key = self.add_client_cert(node=cn) + self.install_node_cert(cert, key, host) + self.expect_connect_succeeds(host) + + resp = self.revoke_client(node=cn)["response"] + # Install the replacement cert returned by revoke-client. + self.install_node_cert(resp["cert_path"], resp["key_path"], host) + self.expect_connect_succeeds(host) + + def test_revoke_node_evicts_per_cn(self): + """Default revoke for node:X evicts only handles whose machine matches X. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_revoke_node_evicts_per_cn + """ + # Create the container BEFORE enabling per-pool cert auth — once + # auth is enabled, add_container's daos invocation on the driver + # would hit DER_NO_CERT (driver has no per-pool cert). + self.add_pool(connect=False) + self.add_container(self.pool) + self.enable_pool_cert_auth() + host = self.hostlist_clients[0:1] + cn = str(host[0]) + cert, key = self.add_client_cert(node=cn) + self.install_node_cert(cert, key, host) + # Plant a live pool handle whose machine name matches the CN we're + # about to revoke. The holder runs pydaos on `host` so server-side + # eviction has a real, machine-bound handle to count. + with self.hold_pool_connection_on(host): + resp = self.revoke_client(node=cn)["response"] + if resp.get("evict_scope") != "machine": + self.fail(f"expected evict_scope=machine, got {resp.get('evict_scope')}") + if resp.get("handles_evicted", 0) <= 0: + self.fail("expected handles_evicted > 0, got 0") + + self.expect_connect_rejected(host) + + # Replacement must work after the holder is torn down. + self.install_node_cert(resp["cert_path"], resp["key_path"], host) + self.expect_connect_succeeds(host) + + def test_revoke_unknown_node_zero_count(self): + """Revoking a non-existent node yields zero evict count (typo signal). + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_revoke_unknown_node_zero_count + """ + self.setup_pool_with_cert_auth() + resp = self.revoke_client(node="nonexistent-host-name")["response"] + if resp.get("evict_scope") != "machine": + self.fail(f"expected evict_scope=machine, got {resp.get('evict_scope')}") + if resp.get("handles_evicted", -1) != 0: + self.fail(f"expected handles_evicted=0, got {resp.get('handles_evicted')}") + + def test_revoke_no_evict_keeps_handle(self): + """--no-evict advances the watermark without dropping live handles. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_revoke_no_evict_keeps_handle + """ + # See test_revoke_node_evicts_per_cn for why we don't use + # setup_pool_with_cert_auth here: add_container must run BEFORE + # per-pool cert auth is enabled on the pool. + self.add_pool(connect=False) + self.add_container(self.pool) + self.enable_pool_cert_auth() + host = self.hostlist_clients[0:1] + cn = str(host[0]) + cert, key = self.add_client_cert(node=cn) + self.install_node_cert(cert, key, host) + + # Plant a live, machine-bound handle so --no-evict has something to + # preserve. The holder runs a heartbeat pool_query against its own + # handle and exits non-zero on the first failure; "process still + # alive after revoke" is the canary signal that the existing + # handle was not torn down. + with self.hold_pool_connection_on(host): + resp = self.revoke_client(node=cn, no_evict=True)["response"] + if resp.get("evict_scope") != "none": + self.fail(f"expected evict_scope=none, got {resp.get('evict_scope')}") + if resp.get("handles_evicted", -1) != 0: + self.fail(f"expected handles_evicted=0, got {resp.get('handles_evicted')}") + + # Give the heartbeat loop a couple of cycles to either keep + # going or trip on a server-side eviction. + time.sleep(5) + self.assert_holder_still_alive_on(host) + + # Watermark advanced: a fresh connect from the same CN is blocked + # even though the existing handle was left alone. + self.expect_connect_rejected(host) + + # Install the replacement cert so framework teardown (which shells + # out to `daos container destroy`) can reconnect to the pool; + # otherwise cleanup hits DER_BAD_CERT and the test is marked + # TestSetupFail. + self.install_node_cert(resp["cert_path"], resp["key_path"], host) + + def test_tenant_revocation_blocks_all_holders(self): + """Revoking a tenant CN must reject every host using that cert. + + :avocado: tags=all,daily_regression + :avocado: tags=vm + :avocado: tags=security,pool,pool_cert + :avocado: tags=PoolNodeAuthRevokeTest,test_tenant_revocation_blocks_all_holders + """ + self.setup_pool_with_cert_auth() + if len(self.hostlist_clients) < 2: + self.fail("test requires at least 2 client hosts") + h1, h2 = self.hostlist_clients[0:1], self.hostlist_clients[1:2] + + cert, key = self.add_client_cert(tenant="teamA") + self.install_node_cert(cert, key, h1) + self.install_node_cert(cert, key, h2) + # Connect succeeds from either host. + self.expect_connect_succeeds(h1) + self.expect_connect_succeeds(h2) + + resp = self.revoke_client(tenant="teamA")["response"] + # Tenant revocation has no per-CN selectivity, so default mode evicts + # the whole pool. + if resp.get("evict_scope") != "pool": + self.fail(f"expected evict_scope=pool, got {resp.get('evict_scope')}") + # Every host using the tenant cert must be rejected. + self.expect_connect_rejected(h1) + self.expect_connect_rejected(h2) diff --git a/src/tests/ftest/security/pool_node_auth_revoke.yaml b/src/tests/ftest/security/pool_node_auth_revoke.yaml new file mode 100644 index 00000000000..2cbff0184e2 --- /dev/null +++ b/src/tests/ftest/security/pool_node_auth_revoke.yaml @@ -0,0 +1,34 @@ +# (C) Copyright 2026 Hewlett Packard Enterprise Development LP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +hosts: + test_servers: 3 + test_clients: 2 +timeout: 1200 +server_config: + name: daos_server + port: 10001 + engines_per_host: 1 + engines: + 0: + targets: 4 + nr_xs_helpers: 0 + storage: + 0: + class: ram + scm_mount: /mnt/daos + scm_size: 4 + system_ram_reserved: 1 +pool: + scm_size: 134217728 + svc_redun_fac: 1 + transport_config: + allow_insecure: False +agent_config: + transport_config: + allow_insecure: False +dmg: + transport_config: + allow_insecure: False +container: + control_method: daos diff --git a/src/tests/ftest/util/dmg_utils.py b/src/tests/ftest/util/dmg_utils.py index e4b51e72c40..5bcfff360f2 100644 --- a/src/tests/ftest/util/dmg_utils.py +++ b/src/tests/ftest/util/dmg_utils.py @@ -1028,6 +1028,50 @@ def pool_upgrade(self, pool): """ return self._get_json_result(("pool", "upgrade"), pool=pool) + def pool_set_cert(self, pool, daos_ca_key=None, output=None, cert=None, + replace=False, append=False): + """Install a pool CA via dmg pool set-cert (generate or import mode).""" + return self._get_json_result( + ("pool", "set-cert"), pool=pool, + daos_ca_key=daos_ca_key, output=output, cert=cert, + replace=replace, append=append) + + def pool_get_cert(self, pool, with_bundle=False): + """Display the pool's CA bundle. + + When with_bundle is True, the JSON response also contains a + `bundle` field with the PEM-encoded CA bundle — useful for + recovering the bundle from a server when the original local + --output files have been lost. + """ + return self._get_json_result( + ("pool", "get-cert"), pool=pool, with_bundle=with_bundle) + + def pool_delete_cert(self, pool, fingerprint=None, delete_all=False): + """Remove one (by fingerprint) or all CAs from the pool's bundle.""" + return self._get_json_result( + ("pool", "delete-cert"), pool=pool, fingerprint=fingerprint, + **{"all": delete_all}) + + def pool_add_client(self, pool, pool_ca_key, output, node=None, tenant=None): + """Mint client certs signed by the pool CA (offline).""" + return self._get_json_result( + ("pool", "add-client"), pool=pool, pool_ca_key=pool_ca_key, + output=output, node=node, tenant=tenant) + + def pool_revoke_client(self, pool, pool_ca_key, output, + node=None, tenant=None, + evict_all_handles=False, no_evict=False): + """Advance the revocation watermark and mint a replacement cert.""" + return self._get_json_result( + ("pool", "revoke-client"), pool=pool, pool_ca_key=pool_ca_key, + output=output, node=node, tenant=tenant, + evict_all_handles=evict_all_handles, no_evict=no_evict) + + def pool_list_revocations(self, pool): + """List per-CN revocation watermarks for the pool.""" + return self._get_json_result(("pool", "list-revocations"), pool=pool) + def cont_set_owner(self, pool, cont, user=None, group=None): """Dmg container set-owner to the specified new user/group. diff --git a/src/tests/ftest/util/dmg_utils_base.py b/src/tests/ftest/util/dmg_utils_base.py index 8447115a171..3ad5041e23e 100644 --- a/src/tests/ftest/util/dmg_utils_base.py +++ b/src/tests/ftest/util/dmg_utils_base.py @@ -391,8 +391,12 @@ def get_sub_command_class(self): """Get the dmg pool sub command object.""" if self.sub_command.value == "create": self.sub_command_class = self.CreateSubCommand() + elif self.sub_command.value == "add-client": + self.sub_command_class = self.AddClientSubCommand() elif self.sub_command.value == "delete-acl": self.sub_command_class = self.DeleteAclSubCommand() + elif self.sub_command.value == "delete-cert": + self.sub_command_class = self.DeleteCertSubCommand() elif self.sub_command.value == "destroy": self.sub_command_class = self.DestroySubCommand() elif self.sub_command.value == "drain": @@ -405,10 +409,14 @@ def get_sub_command_class(self): self.sub_command_class = self.ExtendSubCommand() elif self.sub_command.value == "get-acl": self.sub_command_class = self.GetAclSubCommand() + elif self.sub_command.value == "get-cert": + self.sub_command_class = self.GetCertSubCommand() elif self.sub_command.value == "get-prop": self.sub_command_class = self.GetPropSubCommand() elif self.sub_command.value == "list": self.sub_command_class = self.ListSubCommand() + elif self.sub_command.value == "list-revocations": + self.sub_command_class = self.ListRevocationsSubCommand() elif self.sub_command.value == "overwrite-acl": self.sub_command_class = self.OverwriteAclSubCommand() elif self.sub_command.value == "query": @@ -417,6 +425,10 @@ def get_sub_command_class(self): self.sub_command_class = self.QueryTargetsSubCommand() elif self.sub_command.value == "rebuild": self.sub_command_class = self.RebuildSubCommand() + elif self.sub_command.value == "revoke-client": + self.sub_command_class = self.RevokeClientSubCommand() + elif self.sub_command.value == "set-cert": + self.sub_command_class = self.SetCertSubCommand() elif self.sub_command.value == "set-prop": self.sub_command_class = self.SetPropSubCommand() elif self.sub_command.value == "update-acl": @@ -635,6 +647,72 @@ def __init__(self): super().__init__("/run/dmg/pool/upgrade/*", "upgrade") self.pool = BasicParameter(None, position=1) + class SetCertSubCommand(CommandWithParameters): + """Defines an object for the dmg pool set-cert command.""" + + def __init__(self): + """Create a dmg pool set-cert command object.""" + super().__init__("/run/dmg/pool/set-cert/*", "set-cert") + self.pool = BasicParameter(None, position=1) + self.daos_ca_key = FormattedParameter("--daos-ca-key={}", None) + self.output = FormattedParameter("--output={}", None) + self.cert = FormattedParameter("--cert={}", None) + self.replace = FormattedParameter("--replace", False) + self.append = FormattedParameter("--append", False) + + class GetCertSubCommand(CommandWithParameters): + """Defines an object for the dmg pool get-cert command.""" + + def __init__(self): + """Create a dmg pool get-cert command object.""" + super().__init__("/run/dmg/pool/get-cert/*", "get-cert") + self.pool = BasicParameter(None, position=1) + self.with_bundle = FormattedParameter("--with-bundle", False) + + class DeleteCertSubCommand(CommandWithParameters): + """Defines an object for the dmg pool delete-cert command.""" + + def __init__(self): + """Create a dmg pool delete-cert command object.""" + super().__init__("/run/dmg/pool/delete-cert/*", "delete-cert") + self.pool = BasicParameter(None, position=1) + self.fingerprint = FormattedParameter("--fingerprint={}", None) + self.all = FormattedParameter("--all", False) + + class AddClientSubCommand(CommandWithParameters): + """Defines an object for the dmg pool add-client command.""" + + def __init__(self): + """Create a dmg pool add-client command object.""" + super().__init__("/run/dmg/pool/add-client/*", "add-client") + self.pool = BasicParameter(None, position=1) + self.pool_ca_key = FormattedParameter("--pool-ca-key={}", None) + self.output = FormattedParameter("--output={}", None) + self.node = FormattedParameter("--node={}", None) + self.tenant = FormattedParameter("--tenant={}", None) + + class RevokeClientSubCommand(CommandWithParameters): + """Defines an object for the dmg pool revoke-client command.""" + + def __init__(self): + """Create a dmg pool revoke-client command object.""" + super().__init__("/run/dmg/pool/revoke-client/*", "revoke-client") + self.pool = BasicParameter(None, position=1) + self.pool_ca_key = FormattedParameter("--pool-ca-key={}", None) + self.output = FormattedParameter("--output={}", None) + self.node = FormattedParameter("--node={}", None) + self.tenant = FormattedParameter("--tenant={}", None) + self.evict_all_handles = FormattedParameter("--evict-all-handles", False) + self.no_evict = FormattedParameter("--no-evict", False) + + class ListRevocationsSubCommand(CommandWithParameters): + """Defines an object for the dmg pool list-revocations command.""" + + def __init__(self): + """Create a dmg pool list-revocations command object.""" + super().__init__("/run/dmg/pool/list-revocations/*", "list-revocations") + self.pool = BasicParameter(None, position=1) + class ServerSubCommand(CommandWithSubCommand): """Defines an object for the dmg server sub command.""" diff --git a/src/tests/ftest/util/node_auth_test_base.py b/src/tests/ftest/util/node_auth_test_base.py new file mode 100644 index 00000000000..bbc2334847b --- /dev/null +++ b/src/tests/ftest/util/node_auth_test_base.py @@ -0,0 +1,366 @@ +""" + (C) Copyright 2026 Hewlett Packard Enterprise Development LP + + SPDX-License-Identifier: BSD-2-Clause-Patent +""" +import contextlib +import os +import shutil +import sys +import tempfile +import time + +from apricot import TestWithServers +from ClusterShell.NodeSet import NodeSet +from exception_utils import CommandFailure +from file_utils import distribute_files +from run_utils import run_remote + +# Path to the holder script in the ftest source tree (driver-side). ftest +# installs the security directory next to util/, so the holder lives one +# level up + /security/. The remote path is generated per-test in setUp() +# so concurrent runs on the same host can't clobber each other. +_HOLDER_SOURCE_PATH = os.path.normpath( + os.path.join(os.path.dirname(__file__), "..", "security", + "node_cert_handle_holder.py")) + + +class NodeAuthTestBase(TestWithServers): + """Common helpers for per-pool node certificate authentication tests.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.cert_workdir = None + self.agent_node_cert_dir = None + self.pool_ca_key = None + self.pool_ca_cert = None + self._holder_dir = None + self._holder_remote_path = None + self._holder_distributed_hosts = NodeSet() + + def setUp(self): + super().setUp() + # dmg pool set-cert / add-client / revoke-client write artifacts to + # this directory on the test driver host. + self.cert_workdir = os.path.join(self.test_dir, "pool_certs") + os.makedirs(self.cert_workdir, exist_ok=True) + + # Where the agent expects per-pool node certs on client hosts. + sys_name = self.server_managers[0].get_config_value("name") or "daos_server" + self.agent_node_cert_dir = f"/etc/daos/certs/{sys_name}/node_certs" + + # Per-test temporary directory for the holder script and its + # pid/ready/log files on remote hosts. mkdtemp() guarantees a + # unique path that won't collide with concurrent test runs on + # the same client VM. distribute_files mirrors the local path + # to remote, so the same path is valid on both sides. + self._holder_dir = tempfile.mkdtemp(prefix="node_cert_holder_") + self._holder_remote_path = os.path.join(self._holder_dir, "holder.py") + shutil.copy(_HOLDER_SOURCE_PATH, self._holder_remote_path) + self.register_cleanup(self._cleanup_holder_artifacts) + + def _daos_ca_key_path(self): + """Path to the DAOS CA private key on the test driver. + + gen_certificates.sh writes the CA key to {log_dir}/daosCA/private/daosCA.key + with 0400 perms; it intentionally lives apart from /etc/daos/certs (which + only holds public certs distributed to all nodes). + """ + return os.path.join(self.test_env.log_dir, "daosCA", "private", "daosCA.key") + + def setup_pool_with_cert_auth(self): + """Create a pool and install a freshly-minted pool CA on it.""" + self.add_pool(connect=False) + return self.enable_pool_cert_auth(self.pool) + + def enable_pool_cert_auth(self, pool=None): + """Install a freshly-minted pool CA on `pool` (defaults to self.pool). + + After this returns, the pool requires a per-pool client cert to + connect — the test driver's default cert is no longer sufficient. + Registers a cleanup that calls `dmg pool delete-cert --all` on the + specific pool passed here, so the framework's container/pool + teardown (which shells out to daos from the driver) can reach the + pool again. + + The cleanup captures `pool` in its kwargs at registration time + (matching the add_pool/remove_pool pattern at + test_utils_pool.py:101) so it remains correct even if `self.pool` + is later replaced by another `add_pool()` call. LIFO order of + register_cleanup ensures this runs before any cleanup added + before this call (e.g. `add_container`) and before the + framework's auto-destroy of `pool` itself. + + Args: + pool (TestPool, optional): the pool to enable per-pool cert + auth on. Defaults to self.pool. + + Returns: + str: directory containing the freshly-minted CA cert/key files. + """ + if pool is None: + pool = self.pool + # dmg writes files using the canonical lowercase pool UUID; match it + # everywhere we construct cert/key paths from pool.uuid. + uuid_lc = str(pool.uuid).lower() + out_dir = os.path.join(self.cert_workdir, uuid_lc) + os.makedirs(out_dir, exist_ok=True) + self.get_dmg_command().pool_set_cert( + pool=str(pool.uuid), + daos_ca_key=self._daos_ca_key_path(), + output=out_dir) + self.pool_ca_key = os.path.join(out_dir, f"{uuid_lc}_ca.key") + self.pool_ca_cert = os.path.join(out_dir, f"{uuid_lc}_ca.crt") + self.register_cleanup(self._disable_pool_cert_auth, pool=pool) + return out_dir + + def _disable_pool_cert_auth(self, pool): + """Restore default-CA auth on `pool`. Returns a list of errors + per the test framework's cleanup protocol.""" + try: + self.get_dmg_command().pool_delete_cert( + pool=str(pool.uuid), delete_all=True) + except CommandFailure as exc: + return [f"failed to disable per-pool cert auth on {pool.identifier}: {exc}"] + return [] + + def add_client_cert(self, node=None, tenant=None): + """Mint a client cert via dmg pool add-client. Returns (cert, key).""" + uuid_lc = str(self.pool.uuid).lower() + out_dir = os.path.join(self.cert_workdir, "clients") + os.makedirs(out_dir, exist_ok=True) + self.get_dmg_command().pool_add_client( + pool=str(self.pool.uuid), + pool_ca_key=self.pool_ca_key, + output=out_dir, + node=node, tenant=tenant) + name = node if node else tenant + return (os.path.join(out_dir, name, f"{uuid_lc}.crt"), + os.path.join(out_dir, name, f"{uuid_lc}.key")) + + def install_node_cert(self, cert_path, key_path, hosts, pool=None): + """Distribute a node cert+key to the agent's per-pool cert directory.""" + if pool is None: + pool = self.pool + uuid_lc = str(pool.uuid).lower() + owner = self.agent_managers[0].manager.job.certificate_owner + # distribute_files mkdir is unprivileged and can't create directories + # under /etc; pre-create the agent's per-pool cert dir as root. + mkdir_cmd = (f"sudo mkdir -p {self.agent_node_cert_dir} && " + f"sudo chown {owner} {self.agent_node_cert_dir} && " + f"sudo chmod 0700 {self.agent_node_cert_dir}") + result = run_remote(self.log, hosts, mkdir_cmd, timeout=30) + if not result.passed: + self.fail( + f"failed to prepare agent cert dir on {result.failed_hosts}: " + f"{self._remote_output_blob(result)}") + dst_cert = os.path.join(self.agent_node_cert_dir, f"{uuid_lc}.crt") + dst_key = os.path.join(self.agent_node_cert_dir, f"{uuid_lc}.key") + for src, dst, mode in ((cert_path, dst_cert, "0644"), + (key_path, dst_key, "0400")): + distribute_files(self.log, hosts, src, dst, sudo=True, owner=owner) + chmod_result = run_remote(self.log, hosts, f"sudo chmod {mode} {dst}", + timeout=30) + if not chmod_result.passed: + self.fail( + f"failed to chmod {dst} on {chmod_result.failed_hosts}: " + f"{self._remote_output_blob(chmod_result)}") + + def remove_node_cert(self, hosts, pool=None): + """Remove any installed per-pool node cert from the client hosts. + Best-effort; failures are logged but don't fail the test.""" + if pool is None: + pool = self.pool + uuid_lc = str(pool.uuid).lower() + path = os.path.join(self.agent_node_cert_dir, f"{uuid_lc}.*") + run_remote(self.log, hosts, f"sudo rm -f {path}", timeout=30) + + def revoke_client(self, node=None, tenant=None, + evict_all_handles=False, no_evict=False): + """Run dmg pool revoke-client; returns the parsed JSON response.""" + out_dir = os.path.join(self.cert_workdir, "revoked") + os.makedirs(out_dir, exist_ok=True) + return self.get_dmg_command().pool_revoke_client( + pool=str(self.pool.uuid), + pool_ca_key=self.pool_ca_key, + output=out_dir, + node=node, tenant=tenant, + evict_all_handles=evict_all_handles, no_evict=no_evict) + + def _agent_socket_dir(self): + """Where the agent's dRPC socket lives, as configured for this test.""" + return self.agent_managers[0].get_socket_dir() + + def _remote_output_blob(self, result): + """Flatten run_remote stdout+stderr into a single string for diagnostics.""" + lines = [] + for data in result.output: + lines.extend(data.stdout) + lines.extend(data.stderr) + return "\n".join(lines) + + def _daos_env_prefix(self): + """Env-var prefix the remote daos client needs to talk to CART. + + apricot sets D_PROVIDER (and friends) in the test driver's + os.environ so the local daos client picks the right transport; + run_remote starts with a fresh shell, so without an explicit + prefix the remote daos defaults to its compiled-in provider and + crt_proto_query times out trying to reach all servers. + DAOS_AGENT_DRPC_DIR points the client at the agent socket apricot + configured for this run (may be outside /var/run for unprivileged + agents). + """ + parts = [f"DAOS_AGENT_DRPC_DIR={self._agent_socket_dir()}"] + for key in ("D_PROVIDER", "D_INTERFACE", "D_DOMAIN", "D_PORT"): + val = os.environ.get(key) + if val: + parts.append(f"{key}={val}") + return " ".join(parts) + + def _daos_pool_query_on(self, host): + """Run `daos -j pool query ` on `host`; return CommandResult. + + Per-pool node auth is enforced server-side against the connecting + agent's machine name, so a meaningful pool connect test has to run + the daos client on the host whose CN matches the installed cert — + not on the test driver via DaosCommand (which is local-only). + `self.bin` resolves to the install bin directory (e.g. + /opt/daos/install/bin for source builds, /usr/bin for RPMs), so + neither path is hard-coded here. + """ + cmd = (f"{self._daos_env_prefix()} " + f"{os.path.join(self.bin, 'daos')} -j pool query {self.pool.uuid}") + return run_remote(self.log, host, cmd, timeout=60, stderr=True) + + def expect_connect_succeeds(self, host): + """`daos pool query` on `host` must succeed.""" + result = self._daos_pool_query_on(host) + if not result.passed: + self.fail(f"pool connect from {host} expected to succeed; " + f"failed_hosts={result.failed_hosts}; " + f"output:\n{self._remote_output_blob(result)}") + return result + + def expect_connect_rejected(self, host, expected_substring=None): + """`daos pool query` on `host` must fail; optionally assert message.""" + result = self._daos_pool_query_on(host) + if result.passed: + self.fail(f"pool connect from {host} expected to be rejected, " + f"but it succeeded") + if expected_substring: + blob = self._remote_output_blob(result) + if expected_substring not in blob: + self.fail(f"connect rejected with unexpected error: {blob}") + return result + + def _ensure_holder_on(self, host): + """Copy node_cert_handle_holder.py to the per-test holder dir on + `host`. Cached against the set of hosts we've already distributed + to so repeat callers don't re-rsync. distribute_files mirrors the + local→remote path, so the holder ends up at self._holder_remote_path + on the remote (same path used to launch and clean up).""" + new_hosts = NodeSet(str(host)) - self._holder_distributed_hosts + if not new_hosts: + return + distribute_files(self.log, new_hosts, self._holder_remote_path, + self._holder_remote_path, sudo=False) + self._holder_distributed_hosts.add(new_hosts) + + def _cleanup_holder_artifacts(self): + """Remove the per-test holder directory on every host we + distributed to and on the test driver. Best-effort: cleanup + failures are logged but don't fail teardown.""" + if self._holder_distributed_hosts: + run_remote(self.log, self._holder_distributed_hosts, + f"rm -rf {self._holder_dir}", timeout=30) + shutil.rmtree(self._holder_dir, ignore_errors=True) + return [] + + def _holder_pidfile(self, pool_uuid): + return os.path.join(self._holder_dir, f"{pool_uuid}.pid") + + def assert_holder_still_alive_on(self, host): + """Fail unless the holder process started for self.pool is still up. + + The holder's heartbeat loop exits non-zero on the first pool_query + failure, so a still-running PID is the canary signal that an + existing handle hasn't been evicted. Used by --no-evict, which + promises the watermark advance without dropping live handles. + """ + pidfile = self._holder_pidfile(str(self.pool.uuid)) + check = f"pid=$(cat {pidfile}) && kill -0 $pid" + result = run_remote(self.log, host, check, timeout=10, stderr=True) + if not result.passed: + self.fail(f"pool handle holder on {host} is no longer running " + f"(handle was evicted?)") + + @contextlib.contextmanager + def hold_pool_connection_on(self, host): + """Open a real pool handle on `host` and keep it live until exit. + + revoke-client's evict_scope/handles_evicted assertions need a handle + that was opened by an agent on the right machine. The test driver's + local pydaos can't supply that — its machine name and (typically) + installed cert don't match the CN under test. So we launch a tiny + pydaos holder on `host` instead. + """ + self._ensure_holder_on(host) + pool_uuid = str(self.pool.uuid) + # Files are scoped by uuid AND inside the per-test holder dir, so + # concurrent holders for different pools on the same host don't + # collide, and concurrent test runs don't collide either. + pidfile = self._holder_pidfile(pool_uuid) + readyfile = os.path.join(self._holder_dir, f"{pool_uuid}.ready") + logfile = os.path.join(self._holder_dir, f"{pool_uuid}.log") + # Clean up any prior run's leftovers before launching. + run_remote(self.log, host, + f"rm -f {pidfile} {readyfile} {logfile}", + timeout=10) + + # Use the same Python interpreter the test driver was launched with + # — pydaos lives next to it (in the DAOS venv on source builds, in + # site-packages on RPM installs). Cluster nodes share the install + # layout, so the path is valid on `host`. The holder needs the + # DAOS lib64 dir to load libdaos via DaosContext; self.prefix is + # the install prefix apricot resolved from test_env.daos_prefix. + # `nohup CMD &` is enough to detach; we deliberately don't use + # `disown` (a bash builtin) so the command works under any + # remote login shell. clush passes the command to a shell, so + # there's no need to wrap it in `bash -c`. + lib64_dir = os.path.join(self.prefix, "lib64") + launch = ( + f"{self._daos_env_prefix()} " + f"nohup {sys.executable} {self._holder_remote_path} {lib64_dir} " + f"{pool_uuid} {pidfile} {readyfile} " + f">{logfile} 2>&1 /dev/null; " + f"fi; rm -f {pidfile} {readyfile} {logfile}", + timeout=15) diff --git a/src/tests/security/SConscript b/src/tests/security/SConscript index 19876ed4d90..0f3cfa282a9 100644 --- a/src/tests/security/SConscript +++ b/src/tests/security/SConscript @@ -1,11 +1,16 @@ """Build security test""" +# +# (C) Copyright 2026 Hewlett Packard Enterprise Development LP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# def scons(): """Execute build""" Import('env', 'dc_sectest_tgts') - libs = ['$LIBS', 'daos', 'daos_common', 'gurt'] + libs = ['$LIBS', 'daos', 'daos_common', 'gurt', 'uuid'] sec_sources = ['security_test.c', dc_sectest_tgts] acl_sources = ['acl_dump_test.c'] diff --git a/utils/config/daos_agent.yml b/utils/config/daos_agent.yml index 0bae768c53f..fd09bbe74ac 100644 --- a/utils/config/daos_agent.yml +++ b/utils/config/daos_agent.yml @@ -1,3 +1,7 @@ +# (C) Copyright 2026 Hewlett Packard Enterprise Development LP +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# # DAOS agent configuration file. # # Location of this configuration file is determined by first checking for the @@ -183,3 +187,8 @@ # - # iface: ib3 # domain: mlx5_3 + +## Directory containing per-pool node certificates. +## Agent looks for .crt and .key in this directory. +## Default: /etc/daos/certs//node_certs/ +#node_cert_dir: /etc/daos/certs/daos_server/node_certs/ diff --git a/utils/cq/words.dict b/utils/cq/words.dict index 562e6ea1822..3f78cadbf39 100644 --- a/utils/cq/words.dict +++ b/utils/cq/words.dict @@ -288,6 +288,7 @@ mgmt middleware mins mkdir +mkdtemp mnt modprobe mountpoint @@ -310,6 +311,7 @@ namespaces natively nfs nodesperjob +nohup nosec num numa @@ -337,6 +339,7 @@ perf performant pgrep pid +pidfile pids pkgconfig pkill @@ -381,6 +384,7 @@ rdb rdbt readdir readlink +readyfile realloc rebase relink @@ -467,12 +471,14 @@ testcases testdata testFile testname +tempfile testrunner testsuites tgt timestamp timestamps tmp +tmpdir tmpfs toolchain toplevel