diff --git a/cinder/tests/unit/volume/drivers/test_pure.py b/cinder/tests/unit/volume/drivers/test_pure.py
index 6625948e420..d2f631e9e51 100644
--- a/cinder/tests/unit/volume/drivers/test_pure.py
+++ b/cinder/tests/unit/volume/drivers/test_pure.py
@@ -23,6 +23,7 @@ from oslo_utils import units
 from cinder import exception
 from cinder import test
 from cinder.tests.unit import fake_constants as fake
+from cinder.tests.unit import fake_snapshot
 from cinder.tests.unit import fake_volume
 
 
@@ -323,6 +324,108 @@ REPLICATED_VOL_TYPE = {"is_public": True,
                         "<is> True"},
                        "name": "volume_type_2",
                        "id": VOLUME_TYPE_ID}
+MANAGEABLE_PURE_VOLS = [
+    {
+        'name': 'myVol1',
+        'serial': '8E9C7E588B16C1EA00048CCA',
+        'size': 3221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': None,
+    },
+    {
+        'name': 'myVol2',
+        'serial': '8E9C7E588B16C1EA00048CCB',
+        'size': 3221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': None,
+    },
+    {
+        'name': 'myVol3',
+        'serial': '8E9C7E588B16C1EA00048CCD',
+        'size': 3221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': None,
+    }
+]
+MANAGEABLE_PURE_VOL_REFS = [
+    {
+        'reference': {'name': 'myVol1'},
+        'size': 3,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+    },
+    {
+        'reference': {'name': 'myVol2'},
+        'size': 3,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+    },
+    {
+        'reference': {'name': 'myVol3'},
+        'size': 3,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+    }
+]
+
+MANAGEABLE_PURE_SNAPS = [
+    {
+        'name': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder.snap1',
+        'serial': '8E9C7E588B16C1EA00048CCA',
+        'size': 3221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder',
+    },
+    {
+        'name': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder.snap2',
+        'serial': '8E9C7E588B16C1EA00048CCB',
+        'size': 4221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder',
+    },
+    {
+        'name': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder.snap3',
+        'serial': '8E9C7E588B16C1EA00048CCD',
+        'size': 5221225472,
+        'created': '2016-08-05T17:26:34Z',
+        'source': 'volume-fd33de6e-56f6-452d-a7b6-451c11089a9f-cinder',
+    }
+]
+MANAGEABLE_PURE_SNAP_REFS = [
+    {
+        'reference': {'name': MANAGEABLE_PURE_SNAPS[0]['name']},
+        'size': 3,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+        'source_reference': {'name': MANAGEABLE_PURE_SNAPS[0]['source']},
+    },
+    {
+        'reference': {'name': MANAGEABLE_PURE_SNAPS[1]['name']},
+        'size': 4,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+        'source_reference': {'name': MANAGEABLE_PURE_SNAPS[1]['source']},
+    },
+    {
+        'reference': {'name': MANAGEABLE_PURE_SNAPS[2]['name']},
+        'size': 5,
+        'safe_to_manage': True,
+        'reason_not_safe': None,
+        'cinder_id': None,
+        'extra_info': None,
+        'source_reference': {'name': MANAGEABLE_PURE_SNAPS[2]['source']},
+    }
+]
 
 
 class FakePureStorageHTTPError(Exception):
@@ -1552,6 +1655,136 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
         self.assertEqual(expected, actual)
         return context, volume
 
+    def _test_get_manageable_things(self,
+                                    pure_objs=MANAGEABLE_PURE_VOLS,
+                                    expected_refs=MANAGEABLE_PURE_VOL_REFS,
+                                    pure_hosts=list(),
+                                    cinder_objs=list(),
+                                    is_snapshot=False):
+        self.array.list_volumes.return_value = pure_objs
+        self.array.list_hosts.return_value = pure_hosts
+        marker = mock.Mock()
+        limit = mock.Mock()
+        offset = mock.Mock()
+        sort_keys = mock.Mock()
+        sort_dirs = mock.Mock()
+
+        with mock.patch('cinder.volume.utils.paginate_entries_list') as mpage:
+            if is_snapshot:
+                test_func = self.driver.get_manageable_snapshots
+            else:
+                test_func = self.driver.get_manageable_volumes
+            test_func(cinder_objs, marker, limit, offset, sort_keys, sort_dirs)
+            mpage.assert_called_once_with(
+                expected_refs,
+                marker,
+                limit,
+                offset,
+                sort_keys,
+                sort_dirs
+            )
+
+    def test_get_manageable_volumes(self,):
+        """Default success case.
+
+        Given a list of pure volumes from the REST API, give back a list
+        of volume references.
+        """
+        self._test_get_manageable_things(pure_hosts=[PURE_HOST])
+
+    def test_get_manageable_volumes_connected_vol(self):
+        """Make sure volumes connected to hosts are flagged as unsafe."""
+        connected_host = deepcopy(PURE_HOST)
+        connected_host['name'] = 'host2'
+        connected_host['vol'] = MANAGEABLE_PURE_VOLS[0]['name']
+        pure_hosts = [PURE_HOST, connected_host]
+
+        expected_refs = deepcopy(MANAGEABLE_PURE_VOL_REFS)
+        expected_refs[0]['safe_to_manage'] = False
+        expected_refs[0]['reason_not_safe'] = 'Volume connected to host host2.'
+
+        self._test_get_manageable_things(expected_refs=expected_refs,
+                                         pure_hosts=pure_hosts)
+
+    def test_get_manageable_volumes_already_managed(self):
+        """Make sure volumes already owned by cinder are flagged as unsafe."""
+        cinder_vol = fake_volume.fake_volume_obj(mock.MagicMock())
+        cinder_vol.id = VOLUME_ID
+        cinders_vols = [cinder_vol]
+
+        # Have one of our vol names match up with the existing cinder volume
+        purity_vols = deepcopy(MANAGEABLE_PURE_VOLS)
+        purity_vols[0]['name'] = 'volume-' + VOLUME_ID + '-cinder'
+
+        expected_refs = deepcopy(MANAGEABLE_PURE_VOL_REFS)
+        expected_refs[0]['reference'] = {'name': purity_vols[0]['name']}
+        expected_refs[0]['safe_to_manage'] = False
+        expected_refs[0]['reason_not_safe'] = 'Volume already managed.'
+        expected_refs[0]['cinder_id'] = VOLUME_ID
+
+        self._test_get_manageable_things(pure_objs=purity_vols,
+                                         expected_refs=expected_refs,
+                                         pure_hosts=[PURE_HOST],
+                                         cinder_objs=cinders_vols)
+
+    def test_get_manageable_volumes_no_pure_volumes(self):
+        """Expect no refs to be found if no volumes are on Purity."""
+        self._test_get_manageable_things(pure_objs=[],
+                                         expected_refs=[],
+                                         pure_hosts=[PURE_HOST])
+
+    def test_get_manageable_volumes_no_hosts(self):
+        """Success case with no hosts on Purity."""
+        self._test_get_manageable_things(pure_hosts=[])
+
+    def test_get_manageable_snapshots(self):
+        """Default success case.
+
+        Given a list of pure snapshots from the REST API, give back a list
+        of snapshot references.
+        """
+        self._test_get_manageable_things(
+            pure_objs=MANAGEABLE_PURE_SNAPS,
+            expected_refs=MANAGEABLE_PURE_SNAP_REFS,
+            pure_hosts=[PURE_HOST],
+            is_snapshot=True
+        )
+
+    def test_get_manageable_snapshots_already_managed(self):
+        """Make sure snaps already owned by cinder are flagged as unsafe."""
+        cinder_vol = fake_volume.fake_volume_obj(mock.MagicMock())
+        cinder_vol.id = VOLUME_ID
+        cinder_snap = fake_snapshot.fake_snapshot_obj(mock.MagicMock())
+        cinder_snap.id = SNAPSHOT_ID
+        cinder_snap.volume = cinder_vol
+        cinder_snaps = [cinder_snap]
+
+        purity_snaps = deepcopy(MANAGEABLE_PURE_SNAPS)
+        purity_snaps[0]['name'] = 'volume-%s-cinder.snapshot-%s' % (
+            VOLUME_ID, SNAPSHOT_ID
+        )
+
+        expected_refs = deepcopy(MANAGEABLE_PURE_SNAP_REFS)
+        expected_refs[0]['reference'] = {'name': purity_snaps[0]['name']}
+        expected_refs[0]['safe_to_manage'] = False
+        expected_refs[0]['reason_not_safe'] = 'Snapshot already managed.'
+        expected_refs[0]['cinder_id'] = SNAPSHOT_ID
+
+        self._test_get_manageable_things(
+            pure_objs=purity_snaps,
+            expected_refs=expected_refs,
+            cinder_objs=cinder_snaps,
+            pure_hosts=[PURE_HOST],
+            is_snapshot=True
+        )
+
+    def test_get_manageable_snapshots_no_pure_snapshots(self):
+        """Expect no refs to be found if no snapshots are on Purity."""
+        self._test_get_manageable_things(pure_objs=[],
+                                         expected_refs=[],
+                                         pure_hosts=[PURE_HOST],
+                                         is_snapshot=True)
+
     @mock.patch(BASE_DRIVER_OBJ + '._is_volume_replicated_type', autospec=True)
     def test_retype_repl_to_repl(self, mock_is_replicated_type):
         self._test_retype_repl(mock_is_replicated_type, True, True)
diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py
index 29c663e67b7..bf4aff33f46 100644
--- a/cinder/volume/drivers/pure.py
+++ b/cinder/volume/drivers/pure.py
@@ -894,7 +894,7 @@ class PureBaseVolumeDriver(san.SanDriver):
         """
 
         volume_info = self._validate_manage_existing_ref(existing_ref)
-        size = int(math.ceil(float(volume_info["size"]) / units.Gi))
+        size = self._round_bytes_to_gib(volume_info['size'])
 
         return size
 
@@ -970,7 +970,7 @@ class PureBaseVolumeDriver(san.SanDriver):
         self._verify_manage_snap_api_requirements()
         snap_info = self._validate_manage_existing_ref(existing_ref,
                                                        is_snap=True)
-        size = int(math.ceil(float(snap_info["size"]) / units.Gi))
+        size = self._round_bytes_to_gib(snap_info['size'])
         return size
 
     def unmanage_snapshot(self, snapshot):
@@ -989,6 +989,100 @@ class PureBaseVolumeDriver(san.SanDriver):
                                        "new_name": unmanaged_snap_name})
         self._rename_volume_object(snap_name, unmanaged_snap_name)
 
+    def get_manageable_volumes(self, cinder_volumes, marker, limit, offset,
+                               sort_keys, sort_dirs):
+        """List volumes on the backend available for management by Cinder.
+
+        Rule out volumes that are attached to a Purity host or that
+        are already in the list of cinder_volumes. We return references
+        of the volume names for any others.
+        """
+        array = self._get_current_array()
+        pure_vols = array.list_volumes()
+        hosts_with_connections = array.list_hosts(all=True)
+
+        # Put together a map of volumes that are connected to hosts
+        connected_vols = {}
+        for host in hosts_with_connections:
+            vol = host.get('vol')
+            if vol:
+                connected_vols[vol] = host['name']
+
+        # Put together a map of existing cinder volumes on the array
+        # so we can lookup cinder id's by purity volume names
+        existing_vols = {}
+        for cinder_vol in cinder_volumes:
+            existing_vols[self._get_vol_name(cinder_vol)] = cinder_vol.name_id
+
+        manageable_vols = []
+        for pure_vol in pure_vols:
+            vol_name = pure_vol['name']
+            cinder_id = existing_vols.get(vol_name)
+            is_safe = True
+            reason_not_safe = None
+            host = connected_vols.get(vol_name)
+
+            if host:
+                is_safe = False
+                reason_not_safe = _('Volume connected to host %s.') % host
+
+            if cinder_id:
+                is_safe = False
+                reason_not_safe = _('Volume already managed.')
+
+            manageable_vols.append({
+                'reference': {'name': vol_name},
+                'size': self._round_bytes_to_gib(pure_vol['size']),
+                'safe_to_manage': is_safe,
+                'reason_not_safe': reason_not_safe,
+                'cinder_id': cinder_id,
+                'extra_info': None,
+            })
+
+        return volume_utils.paginate_entries_list(
+            manageable_vols, marker, limit, offset, sort_keys, sort_dirs)
+
+    def get_manageable_snapshots(self, cinder_snapshots, marker, limit, offset,
+                                 sort_keys, sort_dirs):
+        """List snapshots on the backend available for management by Cinder."""
+        array = self._get_current_array()
+        pure_snapshots = array.list_volumes(snap=True)
+
+        # Put together a map of existing cinder snapshots on the array
+        # so we can lookup cinder id's by purity snapshot names
+        existing_snapshots = {}
+        for cinder_snap in cinder_snapshots:
+            name = self._get_snap_name(cinder_snap)
+            existing_snapshots[name] = cinder_snap.id
+
+        manageable_snaps = []
+        for pure_snap in pure_snapshots:
+            snap_name = pure_snap['name']
+            cinder_id = existing_snapshots.get(snap_name)
+            is_safe = True
+            reason_not_safe = None
+
+            if cinder_id:
+                is_safe = False
+                reason_not_safe = _("Snapshot already managed.")
+
+            manageable_snaps.append({
+                'reference': {'name': snap_name},
+                'size': self._round_bytes_to_gib(pure_snap['size']),
+                'safe_to_manage': is_safe,
+                'reason_not_safe': reason_not_safe,
+                'cinder_id': cinder_id,
+                'extra_info': None,
+                'source_reference': {'name': pure_snap['source']},
+            })
+
+        return volume_utils.paginate_entries_list(
+            manageable_snaps, marker, limit, offset, sort_keys, sort_dirs)
+
+    @staticmethod
+    def _round_bytes_to_gib(size):
+        return int(math.ceil(float(size) / units.Gi))
+
     def _get_flasharray(self, san_ip, api_token, rest_version=None,
                         verify_https=None, ssl_cert_path=None):
 
diff --git a/releasenotes/notes/pure-list-mangeable-fed4a1b23212f545.yaml b/releasenotes/notes/pure-list-mangeable-fed4a1b23212f545.yaml
new file mode 100644
index 00000000000..a2bed8cc9e1
--- /dev/null
+++ b/releasenotes/notes/pure-list-mangeable-fed4a1b23212f545.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - Add get_manageable_volumes and get_manageable_snapshots implementations for
+    Pure Storage Volume Drivers.