[prev in list] [next in list] [prev in thread] [next in thread]
List: luci-commits
Subject: [Luci-commits] [luci] Fix to cope with cluster membership changes that happen outside of luci. If no
From: rmccabe () fedoraproject ! org (rmccabe)
Date: 2010-09-30 18:57:27
Message-ID: 20100930185727.2B9FF1201DE () lists ! fedorahosted ! org
[Download RAW message or body]
commit bb6cabd0e7b32487b0f389b70164528605d5abd9
Author: Ryan McCabe <rmccabe at redhat.com>
Date: Thu Sep 30 14:56:33 2010 -0400
Fix to cope with cluster membership changes that happen outside of luci. If nodes \
are added or removed since we've last seen the cluster, create or delete database \
node objects as necessary.
luci/controllers/cluster.py | 6 +++-
luci/lib/db_helpers.py | 61 ++++++++++++++++++++++++++++++++++++------
luci/lib/ricci_helpers.py | 9 +++++-
3 files changed, 64 insertions(+), 12 deletions(-)
---
diff --git a/luci/controllers/cluster.py b/luci/controllers/cluster.py
index 8a7999a..742a487 100644
--- a/luci/controllers/cluster.py
+++ b/luci/controllers/cluster.py
@@ -17,7 +17,7 @@ from pylons.i18n import ugettext as _
# project specific imports
from luci.lib.base import BaseController
-from luci.lib.db_helpers import get_cluster_list, get_model_for_cluster, \
get_status_for_cluster, db_remove_cluster, get_agent_for_cluster, get_cluster_db_obj \
+from luci.lib.db_helpers import get_cluster_list, get_model_for_cluster, \
get_status_for_cluster, db_remove_cluster, get_agent_for_cluster, get_cluster_db_obj, \
reconcile_db_with_conf import luci.lib.ricci_helpers as rh
from luci.lib.flash2 import flash2
import luci.widget_validators.validate_cluster_prop as vcp
@@ -108,6 +108,10 @@ class IndividualClusterController(BaseController):
def get_model(self):
if not self.model:
self.model = get_model_for_cluster(self.name, self.get_agent())
+ try:
+ reconcile_db_with_conf(self.name, self.model.getNodeNames())
+ except:
+ log.exception("Error reconciling db with conf")
return self.model
def get_status(self):
diff --git a/luci/lib/db_helpers.py b/luci/lib/db_helpers.py
index bfd98ff..7322a51 100644
--- a/luci/lib/db_helpers.py
+++ b/luci/lib/db_helpers.py
@@ -19,6 +19,8 @@ from luci.lib.ricci_defines import RICCI_BATCH_FAILURES_MAX
from luci.lib.ricci_communicator import RicciCommunicator
import luci.lib.ricci_queries as rq
+from tg import app_globals
+
import transaction
import logging
log = logging.getLogger(__name__)
@@ -234,24 +236,65 @@ def db_remove_cluster(cluster_name):
return False
return True
-def db_remove_cluster_node(cluster_name, node_name):
- node_to_remove = None
+def db_remove_cluster_nodes(cluster_obj, node_list):
+ kill_list = []
try:
- cluster_obj = get_cluster_db_obj(cluster_name)
for i in cluster_obj.nodes:
- if i.node_name == node_name or i.hostname == node_name:
- node_to_remove = i
- break
+ if i.node_name in node_list or i.hostname in node_list:
+ kill_list.append(i)
- if node_to_remove is not None:
- DBSession.delete(node_to_remove)
+ if len(kill_list) is not None:
+ [DBSession.delete(i) for i in kill_list]
DBSession.flush()
transaction.commit()
return True
except:
- log.exception('Error removing node "%s" from the database' % node_name)
+ log.exception('Error removing nodes "%s" from the database'
+ % ', '.join(node_list))
return False
+def db_add_cluster_node(cluster_obj, name, ricci_host=None, ricci_port=None):
+ node_obj = Node(node_name=name,
+ hostname=ricci_host or name,
+ ipaddr=ricci_host or name,
+ display_name=name,
+ port=ricci_port or app_globals.DEFAULT_RICCI_PORT,
+ cluster=[cluster_obj])
+ DBSession.add(node_obj)
+
+# We keep a list of the nodes for each cluster (and some associated
+# data (e.g., ricci hostname, ricci port) in our local database. If changes
+# are made to the cluster membership outside of this luci instance, our
+# node info may diverge from the info in the current cluster.conf.
+# Consequentially, we need to reconcile the node list info we get from
+# ricci (which it gets from modclusterd) with our database.
+def reconcile_db_with_conf(cluster_name, conf_nodelist):
+ cluster_obj = get_cluster_db_obj(cluster_name)
+ if cluster_obj == None:
+ # This should probably never happen.
+ log.error('No cluster database object was found for cluster "%s"'
+ % cluster_name)
+ return None
+
+ db_nodelist = set([i.node_name for i in cluster_obj.nodes])
+ conf_nodelist = set(conf_nodelist)
+
+ stale_nodes = db_nodelist - conf_nodelist
+ if len(stale_nodes) > 0:
+ # we need to purge the db objects for these (former) nodes
+ ret = db_remove_cluster_nodes(cluster_obj, stale_nodes)
+ if ret is not True:
+ log.debug('An error occurred while attempting to remove stale DB objects \
for nodes "%s"' % ', '.join(stale_nodes)) +
+ new_nodes = conf_nodelist - db_nodelist
+ if len(new_nodes) > 0:
+ # we need to create a new database entry for these nodes
+ for i in new_nodes:
+ db_add_cluster_node(cluster_obj, i)
+ DBSession.flush()
+ transaction.commit()
+ return conf_nodelist != db_nodelist
+
def get_cluster_task_status(cluster_name):
task_status = {}
diff --git a/luci/lib/ricci_helpers.py b/luci/lib/ricci_helpers.py
index db897cc..511cb39 100644
--- a/luci/lib/ricci_helpers.py
+++ b/luci/lib/ricci_helpers.py
@@ -12,7 +12,7 @@ from pylons.i18n import ugettext as _
from luci.model import metadata, DBSession
from luci.model.objects import Node, Cluster, Task
from luci.lib.cluster_status import ClusterStatus
-from luci.lib.db_helpers import get_cluster_db_obj, get_node_by_host, \
get_agent_for_cluster, get_node_by_name, db_remove_cluster_node +from \
luci.lib.db_helpers import get_cluster_db_obj, get_node_by_host, \
get_agent_for_cluster, get_node_by_name, db_remove_cluster_nodes from \
luci.lib.ricci_communicator import RicciCommunicator import luci.lib.ricci_queries \
as rq import luci.lib.luci_tasks as luci_tasks
@@ -494,9 +494,14 @@ def cluster_node_delete(cluster_name, cluster_model, node_list):
for node in node_list:
try:
cluster_model.deleteNodeByName(node)
- db_remove_cluster_node(cluster_name, node)
except Exception, e:
log.exception('Unable to delete node "%s" from the cluster \
configuration' % node) +
+ try:
+ db_remove_cluster_nodes(cluster_obj, node_list)
+ except Exception, e:
+ log.exception('Unable to delete nodes "%s" from the cluster configuration' % ', \
'.join(node_list)) +
update_cluster_conf(cluster_model)
def cluster_svc_start(cluster_name, svc_name, target_node=None):
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic