diff --git a/senlinclient/tests/unit/v1/test_policy.py b/senlinclient/tests/unit/v1/test_policy.py
index cd3851cf..9c4164d0 100644
--- a/senlinclient/tests/unit/v1/test_policy.py
+++ b/senlinclient/tests/unit/v1/test_policy.py
@@ -368,3 +368,56 @@ class TestPolicyDelete(TestPolicy):
 
         mock_stdin.readline.assert_called_with()
         self.mock_client.delete_policy.assert_not_called()
+
+
+class TestPolicyValidate(TestPolicy):
+    spec_path = 'senlinclient/tests/test_specs/deletion_policy.yaml'
+    response = {"policy": {
+        "created_at": None,
+        "data": {},
+        "domain": 'null',
+        "id": None,
+        "name": "validated_policy",
+        "project": "5f1cc92b578e4e25a3b284179cf20a9b",
+        "spec": {
+            "description": "A policy for choosing victim node(s) from a "
+                           "cluster for deletion.",
+            "properties": {
+                "criteria": "OLDEST_FIRST",
+                "destroy_after_deletion": True,
+                "grace_period": 60,
+                "reduce_desired_capacity": False
+            },
+            "type": "senlin.policy.deletion",
+            "version": 1.0
+        },
+        "type": "senlin.policy.deletion-1.0",
+        "updated_at": 'null',
+        "user": "2d7aca950f3e465d8ef0c81720faf6ff"
+    }}
+    defaults = {
+        "spec": {
+            "version": 1,
+            "type": "senlin.policy.deletion",
+            "description": "A policy for choosing victim node(s) from a "
+                           "cluster for deletion.",
+            "properties": {
+                "destroy_after_deletion": True,
+                "grace_period": 60,
+                "reduce_desired_capacity": False,
+                "criteria": "OLDEST_FIRST"
+            }
+        }
+    }
+
+    def setUp(self):
+        super(TestPolicyValidate, self).setUp()
+        self.cmd = osc_policy.ValidatePolicy(self.app, None)
+        self.mock_client.validate_policy = mock.Mock(
+            return_value=sdk_policy.Policy(**self.response['policy']))
+
+    def test_policy_validate(self):
+        arglist = ['--spec-file', self.spec_path]
+        parsed_args = self.check_parser(self.cmd, arglist, [])
+        self.cmd.take_action(parsed_args)
+        self.mock_client.validate_policy.assert_called_with(**self.defaults)
diff --git a/senlinclient/tests/unit/v1/test_shell.py b/senlinclient/tests/unit/v1/test_shell.py
index 7c2e39f5..5e2e9162 100644
--- a/senlinclient/tests/unit/v1/test_shell.py
+++ b/senlinclient/tests/unit/v1/test_shell.py
@@ -641,6 +641,25 @@ class ShellTest(testtools.TestCase):
         msg = _("Failed to delete some of the specified policy(s).")
         self.assertEqual(msg, six.text_type(ex))
 
+    @mock.patch.object(utils, 'get_spec_content')
+    def test_do_policy_validate(self, mock_get):
+        service = mock.Mock()
+        spec = mock.Mock()
+        mock_get.return_value = spec
+        args = {
+            'spec_file': 'policy_file',
+        }
+        args = self._make_args({'spec_file': 'policy_file'})
+        attrs = {
+            'spec': spec,
+        }
+        policy = mock.Mock()
+        policy.to_dict.return_value = {}
+        service.validate_policy.return_value = policy
+        sh.do_policy_validate(service, args)
+        mock_get.assert_called_once_with(args.spec_file)
+        service.validate_policy.assert_called_once_with(**attrs)
+
     @mock.patch.object(utils, 'print_list')
     def test_do_cluster_list(self, mock_print):
         service = mock.Mock()
diff --git a/senlinclient/v1/client.py b/senlinclient/v1/client.py
index 2b89da27..af644a71 100644
--- a/senlinclient/v1/client.py
+++ b/senlinclient/v1/client.py
@@ -150,6 +150,14 @@ class Client(object):
         """
         return self.service.delete_policy(policy, ignore_missing)
 
+    def validate_policy(self, **attrs):
+        """validate a policy spec
+
+        Doc link:
+        http://developer.openstack.org/api-ref-clustering-v1.html#validatePolicy
+        """
+        return self.service.validate_policy(**attrs)
+
     def clusters(self, **queries):
         """List clusters
 
diff --git a/senlinclient/v1/policy.py b/senlinclient/v1/policy.py
index c888f6d9..6fa62c2b 100644
--- a/senlinclient/v1/policy.py
+++ b/senlinclient/v1/policy.py
@@ -269,3 +269,47 @@ class DeletePolicy(command.Command):
                                    {'count': failure_count,
                                    'total': len(parsed_args.policy)})
         print('Policy deleted: %s' % parsed_args.policy)
+
+
+class ValidatePolicy(command.ShowOne):
+    """Validate a policy."""
+
+    log = logging.getLogger(__name__ + ".ValidatePolicy")
+
+    def get_parser(self, prog_name):
+        parser = super(ValidatePolicy, self).get_parser(prog_name)
+        parser.add_argument(
+            '--spec-file',
+            metavar='<spec-file>',
+            required=True,
+            help=_('The spec file used to create the policy')
+        )
+        return parser
+
+    def take_action(self, parsed_args):
+        self.log.debug("take_action(%s)", parsed_args)
+
+        senlin_client = self.app.client_manager.clustering
+        spec = senlin_utils.get_spec_content(parsed_args.spec_file)
+        attrs = {
+            'spec': spec,
+        }
+
+        policy = senlin_client.validate_policy(**attrs)
+        formatters = {
+            'spec': senlin_utils.json_formatter
+        }
+        columns = [
+            'created_at',
+            'data',
+            'domain',
+            'id',
+            'name',
+            'project',
+            'spec',
+            'type',
+            'updated_at',
+            'user'
+        ]
+        return columns, utils.get_dict_properties(policy.to_dict(), columns,
+                                                  formatters=formatters)
diff --git a/senlinclient/v1/shell.py b/senlinclient/v1/shell.py
index fcddd7fc..08103f0f 100644
--- a/senlinclient/v1/shell.py
+++ b/senlinclient/v1/shell.py
@@ -431,6 +431,24 @@ def do_policy_delete(service, args):
     print('Policy deleted: %s' % args.id)
 
 
+@utils.arg('-s', '--spec-file', metavar='<SPEC_FILE>', required=True,
+           help=_('The spec file used to create the policy.'))
+def do_policy_validate(service, args):
+    """VAlidate a policy spec."""
+    show_deprecated('senlin policy-validate',
+                    'openstack cluster policy validate')
+    spec = utils.get_spec_content(args.spec_file)
+    attrs = {
+        'spec': spec,
+    }
+
+    policy = service.validate_policy(**attrs)
+    formatters = {
+        'metadata': utils.json_formatter,
+        'spec': utils.json_formatter,
+    }
+    utils.print_dict(policy.to_dict(), formatters=formatters)
+
 # CLUSTERS
 
 
diff --git a/setup.cfg b/setup.cfg
index c89aa04c..cb648b39 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -59,6 +59,7 @@ openstack.clustering.v1 =
     cluster_policy_detach = senlinclient.v1.cluster:ClusterPolicyDetach
     cluster_policy_list = senlinclient.v1.policy:ListPolicy
     cluster_policy_show = senlinclient.v1.policy:ShowPolicy
+    cluster_policy_validate = senlinclient.v1.policy:ValidatePolicy
     cluster_policy_type_list = senlinclient.v1.policy_type:PolicyTypeList
     cluster_policy_type_show = senlinclient.v1.policy_type:PolicyTypeShow
     cluster_policy_update = senlinclient.v1.policy:UpdatePolicy