diff --git a/ceilometer/hardware/discovery.py b/ceilometer/hardware/discovery.py
index b15896c786..d21ff8edc6 100644
--- a/ceilometer/hardware/discovery.py
+++ b/ceilometer/hardware/discovery.py
@@ -32,10 +32,26 @@ OPTS = [
                help='SNMPd user name of all nodes running in the cloud.'),
     cfg.StrOpt('readonly_user_password',
                default='password',
-               help='SNMPd password of all the nodes running in the cloud.',
+               help='SNMPd v3 authentication password of all the nodes '
+                    'running in the cloud.',
                secret=True),
+    cfg.StrOpt('readonly_user_auth_proto',
+               choices=['md5', 'sha'],
+               help='SNMPd v3 authentication algorithm of all the nodes '
+                    'running in the cloud'),
+    cfg.StrOpt('readonly_user_priv_proto',
+               choices=['des', 'aes128', '3des', 'aes192', 'aes256'],
+               help='SNMPd v3 encryption algorithm of all the nodes '
+                    'running in the cloud'),
+    cfg.StrOpt('readonly_user_priv_password',
+               help='SNMPd v3 encryption password of all the nodes '
+                    'running in the cloud.',
+               secret=True),
+
+
 ]
-cfg.CONF.register_opts(OPTS, group='hardware')
+CONF = cfg.CONF
+CONF.register_opts(OPTS, group='hardware')
 
 
 class NodesDiscoveryTripleO(plugin_base.DiscoveryBase):
@@ -49,6 +65,31 @@ class NodesDiscoveryTripleO(plugin_base.DiscoveryBase):
     def _address(instance, field):
         return instance.addresses['ctlplane'][0].get(field)
 
+    @staticmethod
+    def _make_resource_url(ip):
+        params = [('readonly_user_auth_proto', 'auth_proto'),
+                  ('readonly_user_priv_proto', 'priv_proto'),
+                  ('readonly_user_priv_password', 'priv_password')]
+        hwconf = CONF.hardware
+        url = hwconf.url_scheme
+        username = hwconf.readonly_user_name
+        password = hwconf.readonly_user_password
+        if username:
+            url += username
+        if password:
+            url += ':' + password
+        if username or password:
+            url += '@'
+        url += ip
+
+        query = "&".join(
+            param + "=" + hwconf.get(conf) for (conf, param) in params
+            if hwconf.get(conf))
+        if query:
+            url += '?' + query
+
+        return url
+
     def discover(self, manager, param=None):
         """Discover resources to monitor.
 
@@ -75,11 +116,7 @@ class NodesDiscoveryTripleO(plugin_base.DiscoveryBase):
         for instance in self.instances.values():
             try:
                 ip_address = self._address(instance, 'addr')
-                final_address = (
-                    cfg.CONF.hardware.url_scheme +
-                    cfg.CONF.hardware.readonly_user_name + ':' +
-                    cfg.CONF.hardware.readonly_user_password + '@' +
-                    ip_address)
+                final_address = self._make_resource_url(ip_address)
 
                 resource = {
                     'resource_id': instance.id,
diff --git a/ceilometer/hardware/inspector/snmp.py b/ceilometer/hardware/inspector/snmp.py
index 339344d11b..69d1a2fdb2 100644
--- a/ceilometer/hardware/inspector/snmp.py
+++ b/ceilometer/hardware/inspector/snmp.py
@@ -16,9 +16,10 @@
 """Inspector for collecting data over SNMP"""
 
 import copy
-from pysnmp.entity.rfc3413.oneliner import cmdgen
 
+from pysnmp.entity.rfc3413.oneliner import cmdgen
 import six
+import six.moves.urllib.parse as urlparse
 
 from ceilometer.hardware.inspector import base
 
@@ -56,6 +57,22 @@ def parse_snmp_return(ret, is_bulk=False):
 EXACT = 'type_exact'
 PREFIX = 'type_prefix'
 
+_auth_proto_mapping = {
+    'md5': cmdgen.usmHMACMD5AuthProtocol,
+    'sha': cmdgen.usmHMACSHAAuthProtocol,
+}
+_priv_proto_mapping = {
+    'des': cmdgen.usmDESPrivProtocol,
+    'aes128': cmdgen.usmAesCfb128Protocol,
+    '3des': cmdgen.usm3DESEDEPrivProtocol,
+    'aes192': cmdgen.usmAesCfb192Protocol,
+    'aes256': cmdgen.usmAesCfb256Protocol,
+}
+_usm_proto_mapping = {
+    'auth_proto': ('authProtocol', _auth_proto_mapping),
+    'priv_proto': ('privProtocol', _priv_proto_mapping),
+}
+
 
 class SNMPInspector(base.Inspector):
     # Default port
@@ -283,9 +300,24 @@ class SNMPInspector(base.Inspector):
 
     @staticmethod
     def _get_auth_strategy(host):
+        options = urlparse.parse_qs(host.query)
+        kwargs = {}
+
+        for key in _usm_proto_mapping:
+            opt = options.get(key, [None])[-1]
+            value = _usm_proto_mapping[key][1].get(opt)
+            if value:
+                kwargs[_usm_proto_mapping[key][0]] = value
+
+        priv_pass = options.get('priv_password', [None])[-1]
+        if priv_pass:
+            kwargs['privKey'] = priv_pass
         if host.password:
+            kwargs['authKey'] = host.password
+
+        if kwargs:
             auth_strategy = cmdgen.UsmUserData(host.username,
-                                               authKey=host.password)
+                                               **kwargs)
         else:
             auth_strategy = cmdgen.CommunityData(host.username or 'public')
         return auth_strategy
diff --git a/ceilometer/tests/unit/agent/test_discovery.py b/ceilometer/tests/unit/agent/test_discovery.py
index bf68c26ba0..a95d2b5689 100644
--- a/ceilometer/tests/unit/agent/test_discovery.py
+++ b/ceilometer/tests/unit/agent/test_discovery.py
@@ -87,11 +87,22 @@ class TestHardwareDiscovery(base.BaseTestCase):
         'flavor_id': 'flavor_id',
     }
 
+    expected_usm = {
+        'resource_id': 'resource_id',
+        'resource_url': ''.join(['snmp://ro_snmp_user:password@0.0.0.0',
+                                 '?priv_proto=aes192',
+                                 '&priv_password=priv_pass']),
+        'mac_addr': '01-23-45-67-89-ab',
+        'image_id': 'image_id',
+        'flavor_id': 'flavor_id',
+    }
+
     def setUp(self):
         super(TestHardwareDiscovery, self).setUp()
         self.discovery = hardware.NodesDiscoveryTripleO()
         self.discovery.nova_cli = mock.MagicMock()
         self.manager = mock.MagicMock()
+        self.CONF = self.useFixture(fixture_config.Config()).conf
 
     def test_hardware_discovery(self):
         self.discovery.nova_cli.instance_get_all.return_value = [
@@ -106,3 +117,13 @@ class TestHardwareDiscovery(base.BaseTestCase):
         self.discovery.nova_cli.instance_get_all.return_value = [instance]
         resources = self.discovery.discover(self.manager)
         self.assertEqual(0, len(resources))
+
+    def test_hardware_discovery_usm(self):
+        self.CONF.set_override('readonly_user_priv_proto', 'aes192',
+                               group='hardware')
+        self.CONF.set_override('readonly_user_priv_password', 'priv_pass',
+                               group='hardware')
+        self.discovery.nova_cli.instance_get_all.return_value = [
+            self.MockInstance()]
+        resources = self.discovery.discover(self.manager)
+        self.assertEqual(self.expected_usm, resources[0])
diff --git a/ceilometer/tests/unit/hardware/inspector/test_snmp.py b/ceilometer/tests/unit/hardware/inspector/test_snmp.py
index 6943b8680f..28e584ecbd 100644
--- a/ceilometer/tests/unit/hardware/inspector/test_snmp.py
+++ b/ceilometer/tests/unit/hardware/inspector/test_snmp.py
@@ -14,6 +14,7 @@
 # under the License.
 """Tests for ceilometer/hardware/inspector/snmp/inspector.py
 """
+import mock
 from oslo_utils import netutils
 from oslotest import mockpatch
 
@@ -202,3 +203,20 @@ class TestSNMPInspector(test_base.BaseTestCase):
             name = rfc1902.ObjectName(oid)
 
         self.assertEqual(oid, str(name))
+
+    @mock.patch.object(snmp.cmdgen, 'UsmUserData')
+    def test_auth_strategy(self, mock_method):
+        host = ''.join(['snmp://a:b@foo?auth_proto=sha',
+                       '&priv_password=pass&priv_proto=aes256'])
+        host = netutils.urlsplit(host)
+        self.inspector._get_auth_strategy(host)
+        mock_method.assert_called_with(
+            'a', authKey='b',
+            authProtocol=snmp.cmdgen.usmHMACSHAAuthProtocol,
+            privProtocol=snmp.cmdgen.usmAesCfb256Protocol,
+            privKey='pass')
+
+        host2 = 'snmp://a:b@foo?&priv_password=pass'
+        host2 = netutils.urlsplit(host2)
+        self.inspector._get_auth_strategy(host2)
+        mock_method.assert_called_with('a', authKey='b', privKey='pass')
diff --git a/releasenotes/notes/add-full-snmpv3-usm-support-ab540c902fa89b9d.yaml b/releasenotes/notes/add-full-snmpv3-usm-support-ab540c902fa89b9d.yaml
new file mode 100644
index 0000000000..7e9dd5cd0a
--- /dev/null
+++ b/releasenotes/notes/add-full-snmpv3-usm-support-ab540c902fa89b9d.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+  - >
+    [`bug 1597618 <https://bugs.launchpad.net/ceilometer/+bug/1597618>`_]
+    Add the full support of snmp v3 user security model.