From 10ddb8962a8ea0fa06eda25ed3b7d6fe209b877e Mon Sep 17 00:00:00 2001
From: huangtianhua <huangtianhua@huawei.com>
Date: Mon, 16 Jan 2017 12:16:46 +0800
Subject: [PATCH] Provide unified _show_resource() for senlin resources

Adds the base class for senlin resources, and override
the method _show_resource() in the base class, all
senlin resources can use it.

Change-Id: If900aa5ff60e1c79ce5e3c1edaa9d15f177751b1
Blueprint: refactor-show-resource
---
 .../resources/openstack/senlin/cluster.py     | 20 ++-------
 .../engine/resources/openstack/senlin/node.py | 12 ++---
 .../resources/openstack/senlin/policy.py      | 13 ++----
 .../resources/openstack/senlin/profile.py     | 13 ++----
 .../resources/openstack/senlin/receiver.py    | 19 ++------
 .../resources/openstack/senlin/res_base.py    | 44 +++++++++++++++++++
 6 files changed, 60 insertions(+), 61 deletions(-)
 create mode 100644 heat/engine/resources/openstack/senlin/res_base.py

diff --git a/heat/engine/resources/openstack/senlin/cluster.py b/heat/engine/resources/openstack/senlin/cluster.py
index c2076f7604..bc54c4aa4c 100644
--- a/heat/engine/resources/openstack/senlin/cluster.py
+++ b/heat/engine/resources/openstack/senlin/cluster.py
@@ -19,12 +19,12 @@ from heat.common.i18n import _
 from heat.engine import attributes
 from heat.engine import constraints
 from heat.engine import properties
-from heat.engine import resource
+from heat.engine.resources.openstack.senlin import res_base
 from heat.engine import support
 from heat.engine import translation
 
 
-class Cluster(resource.Resource):
+class Cluster(res_base.BaseSenlinResource):
     """A resource that creates a Senlin Cluster.
 
     Cluster resource in senlin can create and manage objects of
@@ -32,9 +32,7 @@ class Cluster(resource.Resource):
     The collection of these objects is referred to as a cluster.
     """
 
-    support_status = support.SupportStatus(version='6.0.0')
-
-    default_client_name = 'senlin'
+    entity = 'cluster'
 
     PROPERTIES = (
         NAME, PROFILE, DESIRED_CAPACITY, MIN_SIZE, MAX_SIZE,
@@ -370,18 +368,8 @@ class Cluster(resource.Resource):
             }
             raise exception.StackValidationFailed(message=msg)
 
-    def _resolve_attribute(self, name):
-        if self.resource_id is None:
-            return
-
-        if name == self.ATTR_POLICIES:
-            return self.client().cluster_policies(self.resource_id)
-        cluster = self.client().get_cluster(self.resource_id)
-        return getattr(cluster, name, None)
-
     def _show_resource(self):
-        cluster = self.client().get_cluster(self.resource_id)
-        cluster_dict = cluster.to_dict()
+        cluster_dict = super(Cluster, self)._show_resource()
         cluster_dict[self.ATTR_POLICIES] = self.client().cluster_policies(
             self.resource_id)
         return cluster_dict
diff --git a/heat/engine/resources/openstack/senlin/node.py b/heat/engine/resources/openstack/senlin/node.py
index fd19bf2358..c5609f8143 100644
--- a/heat/engine/resources/openstack/senlin/node.py
+++ b/heat/engine/resources/openstack/senlin/node.py
@@ -17,21 +17,19 @@ from heat.common.i18n import _
 from heat.engine import attributes
 from heat.engine import constraints
 from heat.engine import properties
-from heat.engine import resource
+from heat.engine.resources.openstack.senlin import res_base
 from heat.engine import support
 from heat.engine import translation
 
 
-class Node(resource.Resource):
+class Node(res_base.BaseSenlinResource):
     """A resource that creates a Senlin Node.
 
     Node is an object that belongs to at most one Cluster, it can be created
     based on a profile.
     """
 
-    support_status = support.SupportStatus(version='6.0.0')
-
-    default_client_name = 'senlin'
+    entity = 'node'
 
     PROPERTIES = (
         NAME, METADATA, PROFILE, CLUSTER
@@ -145,10 +143,6 @@ class Node(resource.Resource):
             return True
         return False
 
-    def _show_resource(self):
-        node = self.client().get_node(self.resource_id)
-        return node.to_dict()
-
     def handle_update(self, json_snippet, tmpl_diff, prop_diff):
         actions = []
         if prop_diff:
diff --git a/heat/engine/resources/openstack/senlin/policy.py b/heat/engine/resources/openstack/senlin/policy.py
index 1b849132d7..8f6991d90b 100644
--- a/heat/engine/resources/openstack/senlin/policy.py
+++ b/heat/engine/resources/openstack/senlin/policy.py
@@ -18,21 +18,18 @@ from heat.common import exception
 from heat.common.i18n import _
 from heat.engine import constraints
 from heat.engine import properties
-from heat.engine import resource
-from heat.engine import support
+from heat.engine.resources.openstack.senlin import res_base
 from heat.engine import translation
 
 
-class Policy(resource.Resource):
+class Policy(res_base.BaseSenlinResource):
     """A resource that creates a Senlin Policy.
 
     A policy is a set of rules that can be checked and/or enforced when
     an action is performed on a Cluster.
     """
 
-    support_status = support.SupportStatus(version='6.0.0')
-
-    default_client_name = 'senlin'
+    entity = 'policy'
 
     PROPERTIES = (
         NAME, TYPE, POLICY_PROPS, BINDINGS,
@@ -209,10 +206,6 @@ class Policy(resource.Resource):
             ret = self.check_action_done(actions['add'])
         return ret
 
-    def _show_resource(self):
-        policy = self.client().get_policy(self.resource_id)
-        return policy.to_dict()
-
 
 def resource_mapping():
     return {
diff --git a/heat/engine/resources/openstack/senlin/profile.py b/heat/engine/resources/openstack/senlin/profile.py
index 5e5b503d28..a32d869650 100644
--- a/heat/engine/resources/openstack/senlin/profile.py
+++ b/heat/engine/resources/openstack/senlin/profile.py
@@ -16,20 +16,17 @@
 from heat.common.i18n import _
 from heat.engine import constraints
 from heat.engine import properties
-from heat.engine import resource
-from heat.engine import support
+from heat.engine.resources.openstack.senlin import res_base
 
 
-class Profile(resource.Resource):
+class Profile(res_base.BaseSenlinResource):
     """A resource that creates a Senlin Profile.
 
     Profile resource in senlin is a template describing how to create nodes in
     cluster.
     """
 
-    support_status = support.SupportStatus(version='6.0.0')
-
-    default_client_name = 'senlin'
+    entity = 'profile'
 
     PROPERTIES = (
         NAME, TYPE, METADATA, PROFILE_PROPERTIES,
@@ -86,10 +83,6 @@ class Profile(resource.Resource):
             profile_obj = self.client().get_profile(self.resource_id)
             self.client().update_profile(profile_obj, **prop_diff)
 
-    def _show_resource(self):
-        profile = self.client().get_profile(self.resource_id)
-        return profile.to_dict()
-
 
 def resource_mapping():
     return {
diff --git a/heat/engine/resources/openstack/senlin/receiver.py b/heat/engine/resources/openstack/senlin/receiver.py
index ff903e0da9..8221e16299 100644
--- a/heat/engine/resources/openstack/senlin/receiver.py
+++ b/heat/engine/resources/openstack/senlin/receiver.py
@@ -15,20 +15,17 @@ from heat.common.i18n import _
 from heat.engine import attributes
 from heat.engine import constraints
 from heat.engine import properties
-from heat.engine import resource
-from heat.engine import support
+from heat.engine.resources.openstack.senlin import res_base
 
 
-class Receiver(resource.Resource):
+class Receiver(res_base.BaseSenlinResource):
     """A resource that creates Senlin Receiver.
 
     Receiver is an abstract resource created at the senlin engine
     that can be used to hook the engine to some external event/alarm sources.
     """
 
-    support_status = support.SupportStatus(version='6.0.0')
-
-    default_client_name = 'senlin'
+    entity = 'receiver'
 
     PROPERTIES = (
         CLUSTER, ACTION, NAME, TYPE, PARAMS,
@@ -116,16 +113,6 @@ class Receiver(resource.Resource):
             with self.client_plugin().ignore_not_found:
                 self.client().delete_receiver(self.resource_id)
 
-    def _show_resource(self):
-        recv = self.client().get_receiver(self.resource_id)
-        return recv.to_dict()
-
-    def _resolve_attribute(self, name):
-        if self.resource_id is None:
-            return
-        recv = self.client().get_receiver(self.resource_id)
-        return getattr(recv, name, None)
-
 
 def resource_mapping():
     return {
diff --git a/heat/engine/resources/openstack/senlin/res_base.py b/heat/engine/resources/openstack/senlin/res_base.py
new file mode 100644
index 0000000000..d008f84a98
--- /dev/null
+++ b/heat/engine/resources/openstack/senlin/res_base.py
@@ -0,0 +1,44 @@
+#    Copyright 2015 IBM Corp.
+#
+#    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 oslo_log import log as logging
+
+from heat.common.i18n import _LW
+from heat.engine import resource
+from heat.engine import support
+
+LOG = logging.getLogger(__name__)
+
+
+class BaseSenlinResource(resource.Resource):
+    """A base class for Senlin resources."""
+
+    support_status = support.SupportStatus(version='6.0.0')
+
+    default_client_name = 'senlin'
+
+    def _show_resource(self):
+        method_name = 'get_' + self.entity
+        try:
+            client_method = getattr(self.client(), method_name)
+            res_info = client_method(self.resource_id)
+            return res_info.to_dict()
+        except AttributeError as ex:
+            LOG.warning(_LW("No method to get the resource: %s"), ex)
+
+    def _resolve_attribute(self, name):
+        if self.resource_id is None:
+            return
+        res_info = self._show_resource()
+        return res_info.get(name)