summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohammed Junaid <junaid@redhat.com>2013-02-07 07:42:34 +0530
committerVijay Bellur <vbellur@redhat.com>2013-03-07 00:55:34 -0800
commit598ca6bbaabc0b67708a1ecfbef1372eb9927ed9 (patch)
tree69e1d0e63812cf26701997b396ecd11551247a10
parentb7b5c51bbeb6401c65cc879f7aacb9c7ca1c85b1 (diff)
object-storage: Restoring multi volume support in UFO.
* Currently, the users of UFO are restricted to use just one volume at any given point of time. This patch removes this limitation. * The usage of gluster-swift-gen-builders has also changed. With this commit the users should mention the list of volumes that they want to expose through UFO. So, only the volumes mentioned during the ring file generation can be accessed. Usage: gluster-swift-gen-builders <vol-name1> [<vol-name2>]... This is an intermediate fix until we remove the account, container and object server processes. Once we have this frame work running, it will completely eliminate the ring files. Change-Id: I9ad3808519fec9c7c60ad846c4f8b653117a8337 BUG: 909053 Signed-off-by: Mohammed Junaid <junaid@redhat.com> Reviewed-on: http://review.gluster.org/4485 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com> Reviewed-by: Peter Portante <pportant@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c3
-rwxr-xr-xufo/bin/gluster-swift-gen-builders39
-rw-r--r--ufo/gluster/swift/common/Glusterfs.py2
-rw-r--r--ufo/gluster/swift/common/constraints.py9
-rw-r--r--ufo/gluster/swift/common/ring.py82
-rw-r--r--ufo/test/unit/common/test_ring.py43
6 files changed, 168 insertions, 10 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 8725b79f6..c09aa6260 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -166,7 +166,8 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
NULL };
char *invalid_volnames[] = {"volume", "type", "subvolumes", "option",
- "end-volume", "all", NULL};
+ "end-volume", "all", "volume_not_in_ring",
+ NULL};
char *w = NULL;
int op_count = 0;
int32_t replica_count = 1;
diff --git a/ufo/bin/gluster-swift-gen-builders b/ufo/bin/gluster-swift-gen-builders
index b89cd15fb..37ed50dc3 100755
--- a/ufo/bin/gluster-swift-gen-builders
+++ b/ufo/bin/gluster-swift-gen-builders
@@ -1,9 +1,25 @@
#!/bin/bash
+# Note that these port numbers must match the configured values for the
+# various servers in their configuration files.
+declare -A port=(["account.builder"]=6012 ["container.builder"]=6011 \
+ ["object.builder"]=6010)
+
+builder_files="account.builder container.builder object.builder"
+
function create {
- swift-ring-builder $1 create 0 1 1
- swift-ring-builder $1 add z1-127.0.0.1:$2/$3_ 100.0
+ swift-ring-builder $1 create 1 1 1 >> /tmp/out
+}
+
+function add {
+ swift-ring-builder $1 add z$2-127.0.0.1:$3/$4_ 100.0
+}
+
+function rebalance {
swift-ring-builder $1 rebalance
+}
+
+function build {
swift-ring-builder $1
}
@@ -12,8 +28,17 @@ if [ "$1x" = "x" ]; then
exit 1
fi
-# Note that these port numbers must match the configured values for the
-# various servers in their configuration files.
-create account.builder 6012 $1
-create container.builder 6011 $1
-create object.builder 6010 $1
+for builder_file in $builder_files
+do
+ create $builder_file
+
+ zone=1
+ for volname in $@
+ do
+ add $builder_file $zone ${port[$builder_file]} $volname
+ zone=$(expr $zone + 1)
+ done
+
+ rebalance $builder_file
+ build $builder_file
+done
diff --git a/ufo/gluster/swift/common/Glusterfs.py b/ufo/gluster/swift/common/Glusterfs.py
index 5b49e743d..ce2c8e1aa 100644
--- a/ufo/gluster/swift/common/Glusterfs.py
+++ b/ufo/gluster/swift/common/Glusterfs.py
@@ -67,7 +67,7 @@ def mount(root, drive):
if drive == export:
break
else:
- logging.error('No export found in %r matching drive %s', el, drive)
+ logging.error('No export found in %r matching drive, %s', el, drive)
return False
# NOTE: root is typically the default value of /mnt/gluster-object
diff --git a/ufo/gluster/swift/common/constraints.py b/ufo/gluster/swift/common/constraints.py
index a4fc8008c..dd8662a9d 100644
--- a/ufo/gluster/swift/common/constraints.py
+++ b/ufo/gluster/swift/common/constraints.py
@@ -16,7 +16,8 @@
from webob.exc import HTTPBadRequest
import swift.common.constraints
-from gluster.swift.common import Glusterfs
+import swift.common.ring as _ring
+from gluster.swift.common import Glusterfs, ring
MAX_OBJECT_NAME_COMPONENT_LENGTH = swift.common.constraints.constraints_conf_int(
@@ -80,3 +81,9 @@ def gluster_check_mount(root, drive):
# Replace the original check mount with ours
swift.common.constraints.check_mount = gluster_check_mount
+
+# Save the original Ring class
+__Ring = _ring.Ring
+
+# Replace the original Ring class
+_ring.Ring = ring.Ring
diff --git a/ufo/gluster/swift/common/ring.py b/ufo/gluster/swift/common/ring.py
new file mode 100644
index 000000000..9bac39c75
--- /dev/null
+++ b/ufo/gluster/swift/common/ring.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2013 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ConfigParser import ConfigParser
+from swift.common.ring import ring
+from swift.common.utils import search_tree
+from gluster.swift.common.Glusterfs import SWIFT_DIR
+
+reseller_prefix = "AUTH_"
+conf_files = search_tree(SWIFT_DIR, "proxy-server*", 'conf')
+if conf_files:
+ conf_file = conf_files[0]
+
+_conf = ConfigParser()
+if conf_files and _conf.read(conf_file):
+ if _conf.defaults().get("reseller_prefix", None):
+ reseller_prefix = _conf.defaults().get("reseller_prefix")
+ else:
+ for key, value in _conf._sections.items():
+ if value.get("reseller_prefix", None):
+ reseller_prefix = value["reseller_prefix"]
+ break
+
+if not reseller_prefix.endswith('_'):
+ reseller_prefix = reseller_prefix + '_'
+
+class Ring(ring.Ring):
+ def get_nodes(self, account, container=None, obj=None):
+ """
+ Get the partition and nodes for an account/container/object.
+ If a node is responsible for more than one replica, it will
+ only appear in the output once.
+ :param account: account name
+ :param container: container name
+ :param obj: object name
+ :returns: a tuple of (partition, list of node dicts)
+
+ Each node dict will have at least the following keys:
+ ====== ===============================================================
+ id unique integer identifier amongst devices
+ weight a float of the relative weight of this device as compared to
+ others; this indicates how many partitions the builder will try
+ to assign to this device
+ zone integer indicating which zone the device is in; a given
+ partition will not be assigned to multiple devices within the
+ same zone
+ ip the ip address of the device
+ port the tcp port of the device
+ device the device's name on disk (sdb1, for example)
+ meta general use 'extra' field; for example: the online date, the
+ hardware description
+ ====== ===============================================================
+ """
+ false_node = [{'zone': 1, 'weight': 100.0, 'ip': '127.0.0.1', 'id': 0, \
+ 'meta': '', 'device': 'volume_not_in_ring', \
+ 'port': 6012}]
+ if account.startswith(reseller_prefix):
+ acc_name = account.replace(reseller_prefix, '', 1)
+ else:
+ acc_name = account
+
+ part = 0
+ seen_ids = set()
+ nodes = [dev for dev in self._devs \
+ if dev['device'] == acc_name \
+ and not (dev['id'] in seen_ids \
+ or seen_ids.add(dev['id']))]
+ if not nodes:
+ nodes = false_node
+ return part, nodes
diff --git a/ufo/test/unit/common/test_ring.py b/ufo/test/unit/common/test_ring.py
new file mode 100644
index 000000000..d3dac609c
--- /dev/null
+++ b/ufo/test/unit/common/test_ring.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2013 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import gluster.swift.common.constraints
+from gluster.swift.common.ring import *
+from gluster.swift.common.Glusterfs import SWIFT_DIR
+
+def _mock_ring_data():
+ return [{'zone': 1, 'weight': 100.0, 'ip': '127.0.0.1', 'port': 6012, \
+ 'meta': '', 'device': 'test', 'id': 0},
+ {'zone': 2, 'weight': 100.0, 'ip': '127.0.0.1', 'id': 1, \
+ 'meta': '', 'device': 'iops', 'port': 6012}]
+
+class TestRing(unittest.TestCase):
+ """ Tests for common.utils """
+
+ def setUp(self):
+ self.ring = Ring(SWIFT_DIR, ring_name='object')
+
+ def test_get_notes(self):
+ try:
+ __devs = self.ring._devs
+ self.ring._devs = _mock_ring_data()
+ part, node = self.ring.get_nodes('test')
+ assert node[0]['device'] == 'test'
+ part, node = self.ring.get_nodes('test2')
+ assert node
+ assert node[0]['device'] == 'volume'
+ finally:
+ self.ring._devs = __devs