summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-09-25 04:26:45 +0200
committerSimo Sorce <simo@redhat.com>2015-10-19 12:17:48 -0400
commit0ca07419bbc2c4e499b4c37d2183d82b2640e816 (patch)
treec46bb64f554f7fc26dbcb2f21904a903f669676b
parent1d813cc53b9c03636967600f0e31e0cafb14813c (diff)
downloadcustodia-0ca07419bbc2c4e499b4c37d2183d82b2640e816.tar.gz
custodia-0ca07419bbc2c4e499b4c37d2183d82b2640e816.tar.xz
custodia-0ca07419bbc2c4e499b4c37d2183d82b2640e816.zip
Implement ETCD based Store
Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Christian Heimes <cheimes@redhat.com>
-rw-r--r--custodia/store/etcdstore.py94
-rw-r--r--requirements.txt1
2 files changed, 95 insertions, 0 deletions
diff --git a/custodia/store/etcdstore.py b/custodia/store/etcdstore.py
new file mode 100644
index 0000000..9a9e535
--- /dev/null
+++ b/custodia/store/etcdstore.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file
+
+from __future__ import print_function
+
+import os
+import sys
+
+import etcd
+
+from custodia.store.interface import CSStore, CSStoreError, CSStoreExists
+
+
+def log_error(error):
+ print(error, file=sys.stderr)
+
+
+class EtcdStore(CSStore):
+
+ def __init__(self, config):
+ self.server = config.get('etcd_server', '127.0.0.1')
+ self.port = int(config.get('etcd_port', 4001))
+ self.namespace = config.get('namespace', "/custodia")
+
+ # Initialize the DB by trying to create the default table
+ try:
+ self.etcd = etcd.Client(self.server, self.port)
+ self.etcd.write(self.namespace, None, dir=True)
+ except etcd.EtcdNotFile:
+ # Already exists
+ pass
+ except etcd.EtcdException as err:
+ log_error("Error creating namespace %s: [%r]" % (self.namespace,
+ repr(err)))
+ raise CSStoreError('Error occurred while trying to init db')
+
+ def get(self, key):
+ try:
+ result = self.etcd.get(os.path.join(self.namespace, key))
+ except etcd.EtcdException as err:
+ log_error("Error fetching key %s: [%r]" % (key, repr(err)))
+ raise CSStoreError('Error occurred while trying to get key')
+ return result.value
+
+ def set(self, key, value, replace=False):
+ path = os.path.join(self.namespace, key)
+ try:
+ self.etcd.write(path, value, prevExist=replace)
+ except etcd.EtcdAlreadyExist as err:
+ raise CSStoreExists(str(err))
+ except etcd.EtcdException as err:
+ log_error("Error storing key %s: [%r]" % (key, repr(err)))
+ raise CSStoreError('Error occurred while trying to store key')
+
+ def span(self, key):
+ path = os.path.join(self.namespace, key)
+ try:
+ self.etcd.write(path, None, dir=True, prevExist=False)
+ except etcd.EtcdAlreadyExist as err:
+ raise CSStoreExists(str(err))
+ except etcd.EtcdException as err:
+ log_error("Error storing key %s: [%r]" % (key, repr(err)))
+ raise CSStoreError('Error occurred while trying to store key')
+
+ def list(self, keyfilter='/'):
+ path = os.path.join(self.namespace, keyfilter)
+ if path != '/':
+ path = path.rstrip('/')
+ try:
+ result = self.etcd.read(path, recursive=True)
+ except etcd.EtcdKeyNotFound:
+ return None
+ except etcd.EtcdException as err:
+ log_error("Error listing %s: [%r]" % (keyfilter, repr(err)))
+ raise CSStoreError('Error occurred while trying to list keys')
+
+ value = set()
+ for entry in result.get_subtree():
+ if entry.key == path:
+ continue
+ name = entry.key[len(path):]
+ if entry.dir and not name.endswith('/'):
+ name += '/'
+ value.add(name.lstrip('/'))
+ return sorted(value)
+
+ def cut(self, key):
+ try:
+ self.etcd.delete(os.path.join(self.namespace, key))
+ except etcd.EtcdKeyNotFound:
+ return False
+ except etcd.EtcdException as err:
+ log_error("Error removing key %s: [%r]" % (key, repr(err)))
+ raise CSStoreError('Error occurred while trying to cut key')
+ return True
diff --git a/requirements.txt b/requirements.txt
index 3687329..3746d7c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
jwcrypto
six
+python-etcd