diff --git a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py
index 1d1e440cbdb..7c64c150552 100644
--- a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py
+++ b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py
@@ -675,6 +675,11 @@ class HPE3PARBaseDriver(test.TestCase):
                                      'minor': 5,
                                      'revision': 0}
 
+    wsapi_version_2023 = {'major': 1,
+                          'build': 100000050,
+                          'minor': 10,
+                          'revision': 0}
+
     # Use this to point to latest version of wsapi
     wsapi_version_latest = wsapi_version_for_compression
 
@@ -892,28 +897,41 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
             mock_client.assert_has_calls(expected)
             self.assertEqual(self.STATUS_DONE, status)
 
-    def test_create_volume(self):
+    # (i) wsapi version is old/default
+    # (ii) wsapi version is 2023, then snapCPG isn't required
+    @ddt.data({'wsapi_version': None},
+              {'wsapi_version': HPE3PARBaseDriver.wsapi_version_2023})
+    @ddt.unpack
+    def test_create_volume(self, wsapi_version):
         # setup_mock_client drive with default configuration
         # and return the mock HTTP 3PAR client
-        mock_client = self.setup_driver()
+        mock_client = self.setup_driver(wsapi_version=wsapi_version)
+
         with mock.patch.object(hpecommon.HPE3PARCommon,
                                '_create_client') as mock_create_client:
             mock_create_client.return_value = mock_client
-            self.driver.create_volume(self.volume)
+            if not wsapi_version:
+                # (i) old/default
+                self.driver.create_volume(self.volume)
+            else:
+                # (ii) wsapi 2023
+                common = self.driver._login()
+                common.create_volume(self.volume)
             comment = Comment({
                 "display_name": "Foo Volume",
                 "type": "OpenStack",
                 "name": "volume-d03338a9-9115-48a3-8dfc-35cdfcdc15a7",
                 "volume_id": "d03338a9-9115-48a3-8dfc-35cdfcdc15a7"})
+            optional = {'comment': comment,
+                        'tpvv': True,
+                        'tdvv': False}
+            if not wsapi_version:
+                optional['snapCPG'] = HPE3PAR_CPG_SNAP
             expected = [
                 mock.call.createVolume(
                     self.VOLUME_3PAR_NAME,
                     HPE3PAR_CPG,
-                    2048, {
-                        'comment': comment,
-                        'tpvv': True,
-                        'tdvv': False,
-                        'snapCPG': HPE3PAR_CPG_SNAP})]
+                    2048, optional)]
 
             mock_client.assert_has_calls(expected)
 
@@ -1254,6 +1272,89 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
                     mirror_config=True)]
             mock_client.assert_has_calls(expected)
 
+    @mock.patch.object(volume_types, 'get_volume_type')
+    def test_create_volume_replicated_periodic_2023(self, _mock_volume_types):
+        # setup_mock_client drive with default configuration
+        # and return the mock HTTP 3PAR client
+        conf = self.setup_configuration()
+        self.replication_targets[0]['replication_mode'] = 'periodic'
+        conf.replication_device = self.replication_targets
+        mock_client = self.setup_driver(conf, None, self.wsapi_version_2023)
+        mock_client.getStorageSystemInfo.return_value = (
+            {'id': self.CLIENT_ID})
+        mock_client.getRemoteCopyGroup.side_effect = (
+            hpeexceptions.HTTPNotFound)
+        mock_client.getCPG.return_value = {'domain': None}
+        mock_replicated_client = self.setup_driver(conf, None,
+                                                   self.wsapi_version_2023)
+        mock_replicated_client.getStorageSystemInfo.return_value = (
+            {'id': self.REPLICATION_CLIENT_ID})
+
+        _mock_volume_types.return_value = {
+            'name': 'replicated',
+            'extra_specs': {
+                'replication_enabled': '<is> True',
+                'replication:mode': 'periodic',
+                'replication:sync_period': '900',
+                'volume_type': self.volume_type_replicated}}
+
+        with mock.patch.object(
+                hpecommon.HPE3PARCommon,
+                '_create_client') as mock_create_client, \
+            mock.patch.object(
+                hpecommon.HPE3PARCommon,
+                '_create_replication_client') as mock_replication_client:
+            mock_create_client.return_value = mock_client
+            mock_replication_client.return_value = mock_replicated_client
+
+            common = self.driver._login()
+            return_model = common.create_volume(self.volume_replicated)
+            comment = Comment({
+                "volume_type_name": "replicated",
+                "display_name": "Foo Volume",
+                "name": "volume-d03338a9-9115-48a3-8dfc-35cdfcdc15a7",
+                "volume_type_id": "be9181f1-4040-46f2-8298-e7532f2bf9db",
+                "volume_id": "d03338a9-9115-48a3-8dfc-35cdfcdc15a7",
+                "qos": {},
+                "type": "OpenStack"})
+
+            backend_id = self.replication_targets[0]['backend_id']
+            expected = [
+                mock.call.createVolume(
+                    self.VOLUME_3PAR_NAME,
+                    HPE3PAR_CPG,
+                    2048, {
+                        'comment': comment,
+                        'tpvv': True,
+                        'tdvv': False}),
+                mock.call.getRemoteCopyGroup(self.RCG_3PAR_NAME),
+                mock.call.getCPG(HPE3PAR_CPG),
+                mock.call.createRemoteCopyGroup(
+                    self.RCG_3PAR_NAME,
+                    [{'userCPG': HPE3PAR_CPG_REMOTE,
+                      'targetName': backend_id,
+                      'mode': PERIODIC_MODE}],
+                    {'localUserCPG': HPE3PAR_CPG}),
+                mock.call.addVolumeToRemoteCopyGroup(
+                    self.RCG_3PAR_NAME,
+                    self.VOLUME_3PAR_NAME,
+                    [{'secVolumeName': self.VOLUME_3PAR_NAME,
+                      'targetName': backend_id}],
+                    optional={'volumeAutoCreation': True}),
+                mock.call.modifyRemoteCopyGroup(
+                    self.RCG_3PAR_NAME,
+                    {'targets': [{'syncPeriod': SYNC_PERIOD,
+                                  'targetName': backend_id}]}),
+                mock.call.startRemoteCopy(self.RCG_3PAR_NAME)]
+            mock_client.assert_has_calls(
+                self.get_id_login +
+                self.standard_logout +
+                self.standard_login +
+                expected)
+            self.assertEqual({'replication_status': 'enabled',
+                              'provider_location': self.CLIENT_ID},
+                             return_model)
+
     @mock.patch.object(volume_types, 'get_volume_type')
     def test_create_volume_replicated_sync(self, _mock_volume_types):
         # setup_mock_client drive with default configuration
@@ -4245,10 +4346,16 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
                 expected_retype_specs)
             self.assertEqual(expected_obj, obj)
 
+    # (i) wsapi version is old/default
+    # (ii) wsapi version is 2023, then snapCPG isn't required
+    @ddt.data({'wsapi_version': None},
+              {'wsapi_version': HPE3PARBaseDriver.wsapi_version_2023})
+    @ddt.unpack
     @mock.patch.object(volume_types, 'get_volume_type')
-    def test_manage_existing_with_no_snap_cpg(self, _mock_volume_types):
+    def test_manage_existing_with_no_snap_cpg(self, _mock_volume_types,
+                                              wsapi_version):
         _mock_volume_types.return_value = self.volume_type
-        mock_client = self.setup_driver()
+        mock_client = self.setup_driver(wsapi_version=wsapi_version)
 
         new_comment = Comment({
             "display_name": "Foo Volume",
@@ -4280,15 +4387,20 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
 
             obj = self.driver.manage_existing(volume, existing_ref)
 
+            optional = {'newName': osv_matcher,
+                        'comment': new_comment}
+
+            if not wsapi_version:
+                # (i) old/default
+                # manage_existing() should be setting
+                # blank snapCPG to the userCPG
+                optional['snapCPG'] = 'testUserCpg0'
+
             expected_manage = [
                 mock.call.getVolume(existing_ref['source-name']),
                 mock.call.modifyVolume(
                     existing_ref['source-name'],
-                    {'newName': osv_matcher,
-                     'comment': new_comment,
-                     # manage_existing() should be setting
-                     # blank snapCPG to the userCPG
-                     'snapCPG': 'testUserCpg0'})
+                    optional)
             ]
 
             mock_client.assert_has_calls(self.standard_login + expected_manage)
@@ -6052,16 +6164,21 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
 
             mock_client.assert_has_calls(expected)
 
+    # (i) wsapi version is old/default
+    # (ii) wsapi version is 2023, then snapCPG isn't required
+    @ddt.data({'wsapi_version': None},
+              {'wsapi_version': HPE3PARBaseDriver.wsapi_version_2023})
+    @ddt.unpack
     @mock.patch('cinder.volume.drivers.hpe.hpe_3par_common.HPE3PARCommon.'
                 'get_volume_settings_from_type')
     @mock.patch('cinder.volume.drivers.hpe.hpe_3par_common.HPE3PARCommon.'
                 'is_volume_group_snap_type')
     @mock.patch('cinder.volume.volume_utils.is_group_a_cg_snapshot_type')
     def test_create_group_from_src_group(self, cg_ss_enable, vol_ss_enable,
-                                         typ_info):
+                                         typ_info, wsapi_version):
         cg_ss_enable.return_value = True
         vol_ss_enable.return_value = True
-        mock_client = self.setup_driver()
+        mock_client = self.setup_driver(wsapi_version=wsapi_version)
         task_id = 1
         mock_client.copyVolume.return_value = {'taskid': task_id}
         mock_client.getStorageSystemInfo.return_value = {'id': self.CLIENT_ID}
@@ -6092,6 +6209,10 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
             source_grp = self.fake_group_object(
                 grp_id=self.SRC_CONSIS_GROUP_ID)
 
+            optional = {'online': True,
+                        'tpvv': mock.ANY, 'tdvv': mock.ANY}
+            if not wsapi_version:
+                optional['snapCPG'] = HPE3PAR_CPG
             expected = [
                 mock.call.getCPG(HPE3PAR_CPG),
                 mock.call.createVolumeSet(
@@ -6107,17 +6228,25 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
                     mock.ANY,
                     self.VOLUME_NAME_3PAR,
                     HPE3PAR_CPG,
-                    {'snapCPG': HPE3PAR_CPG, 'online': True,
-                     'tpvv': mock.ANY, 'tdvv': mock.ANY}),
+                    optional),
                 mock.call.addVolumeToVolumeSet(
                     self.CONSIS_GROUP_NAME,
                     self.VOLUME_NAME_3PAR)]
 
             # Create a consistency group from a source consistency group.
-            self.driver.create_group_from_src(
-                context.get_admin_context(), group,
-                [volume], source_group=source_grp,
-                source_vols=[source_volume])
+            if not wsapi_version:
+                # (i) old/default
+                self.driver.create_group_from_src(
+                    context.get_admin_context(), group,
+                    [volume], source_group=source_grp,
+                    source_vols=[source_volume])
+            else:
+                # (ii) wsapi 2023
+                common = self.driver._login()
+                common.create_group_from_src(
+                    context.get_admin_context(), group,
+                    [volume], source_group=source_grp,
+                    source_vols=[source_volume])
 
             mock_client.assert_has_calls(expected)
 
diff --git a/cinder/volume/drivers/hpe/hpe_3par_common.py b/cinder/volume/drivers/hpe/hpe_3par_common.py
index ba4d4ea5ceb..5fa5a7f4f84 100644
--- a/cinder/volume/drivers/hpe/hpe_3par_common.py
+++ b/cinder/volume/drivers/hpe/hpe_3par_common.py
@@ -81,6 +81,7 @@ FLASH_CACHE_API_VERSION = 30201200
 COMPRESSION_API_VERSION = 30301215
 SRSTATLD_API_VERSION = 30201200
 REMOTE_COPY_API_VERSION = 30202290
+API_VERSION_2023 = 100000000
 
 hpe3par_opts = [
     cfg.StrOpt('hpe3par_api_url',
@@ -300,11 +301,12 @@ class HPE3PARCommon(object):
         4.0.16 - In multi host env, fix multi-detach operation. Bug #1958122
         4.0.17 - Added get_manageable_volumes and get_manageable_snapshots.
                  Bug #1819903
+        4.0.19 - Update code to work with new WSAPI (of 2023). Bug #2015746
 
 
     """
 
-    VERSION = "4.0.17"
+    VERSION = "4.0.19"
 
     stats = {}
 
@@ -704,9 +706,12 @@ class HPE3PARCommon(object):
             compression = self.get_compression_policy(
                 type_info['hpe3par_keys'])
 
-            optional = {'online': True, 'snapCPG': snapcpg,
+            optional = {'online': True,
                         'tpvv': tpvv, 'tdvv': tdvv}
 
+            if self.API_VERSION < API_VERSION_2023:
+                optional['snapCPG'] = snapcpg
+
             if compression is not None:
                 optional['compression'] = compression
 
@@ -1004,7 +1009,7 @@ class HPE3PARCommon(object):
                     'comment': json.dumps(new_comment)}
 
         # Ensure that snapCPG is set
-        if 'snapCPG' not in vol:
+        if 'snapCPG' not in vol and self.API_VERSION < API_VERSION_2023:
             new_vals['snapCPG'] = vol['userCPG']
             LOG.info("Virtual volume %(disp)s '%(new)s' snapCPG "
                      "is empty so it will be set to: %(cpg)s",
@@ -2393,9 +2398,14 @@ class HPE3PARCommon(object):
                     comments['qos'] = qos
 
             extras = {'comment': json.dumps(comments),
-                      'snapCPG': snap_cpg,
                       'tpvv': tpvv}
 
+            LOG.debug("self.API_VERSION: %(version)s",
+                      {'version': self.API_VERSION})
+
+            if self.API_VERSION < API_VERSION_2023:
+                extras['snapCPG'] = snap_cpg
+
             # Only set the dedup option if the backend supports it.
             if self.API_VERSION >= DEDUP_API_VERSION:
                 extras['tdvv'] = tdvv
@@ -2466,7 +2476,7 @@ class HPE3PARCommon(object):
                   {'src': src_name, 'dest': dest_name})
 
         optional = {'tpvv': tpvv, 'online': True}
-        if snap_cpg is not None:
+        if snap_cpg is not None and self.API_VERSION < API_VERSION_2023:
             optional['snapCPG'] = snap_cpg
 
         if self.API_VERSION >= DEDUP_API_VERSION:
@@ -4358,15 +4368,17 @@ class HPE3PARCommon(object):
                                                      local_cpg)
                     rcg_target = {'targetName': target['backend_id'],
                                   'mode': replication_mode_num,
-                                  'snapCPG': cpg,
                                   'userCPG': cpg}
+                    if self.API_VERSION < API_VERSION_2023:
+                        rcg_target['snapCPG'] = cpg
                     rcg_targets.append(rcg_target)
                     sync_target = {'targetName': target['backend_id'],
                                    'syncPeriod': replication_sync_period}
                     sync_targets.append(sync_target)
 
-            optional = {'localSnapCPG': vol_settings['snap_cpg'],
-                        'localUserCPG': local_cpg}
+            optional = {'localUserCPG': local_cpg}
+            if self.API_VERSION < API_VERSION_2023:
+                optional['localSnapCPG'] = vol_settings['snap_cpg']
             pool = volume_utils.extract_host(volume['host'], level='pool')
             domain = self.get_domain(pool)
             if domain:
@@ -4381,6 +4393,8 @@ class HPE3PARCommon(object):
                 LOG.error(msg)
                 raise exception.VolumeBackendAPIException(data=msg)
 
+            LOG.debug("created rcg %(name)s", {'name': rcg_name})
+
             # Add volume to remote copy group.
             rcg_targets = []
             for target in self._replication_targets:
@@ -5300,7 +5314,11 @@ class ModifyVolumeTask(flow_utils.CinderTask):
         comment_dict = self._get_new_comment(
             old_comment, new_vvs, new_qos, new_type_name, new_type_id)
 
-        if new_snap_cpg != old_snap_cpg:
+        LOG.debug("API_VERSION: %(ver_1)s, API_VERSION_2023: %(ver_2)s",
+                  {'ver_1': common.API_VERSION,
+                   'ver_2': API_VERSION_2023})
+        if (new_snap_cpg != old_snap_cpg and
+                common.API_VERSION < API_VERSION_2023):
             # Modify the snap_cpg.  This will fail with snapshots.
             LOG.info("Modifying %(volume_name)s snap_cpg from "
                      "%(old_snap_cpg)s to %(new_snap_cpg)s.",
diff --git a/releasenotes/notes/hpe-3par-code-changes-for-new-wsapi-25865a65a428ce46.yaml b/releasenotes/notes/hpe-3par-code-changes-for-new-wsapi-25865a65a428ce46.yaml
new file mode 100644
index 00000000000..82cbc97d930
--- /dev/null
+++ b/releasenotes/notes/hpe-3par-code-changes-for-new-wsapi-25865a65a428ce46.yaml
@@ -0,0 +1,4 @@
+fixes:
+  - |
+    HPE 3PAR driver `Bug #2015746 <https://bugs.launchpad.net/cinder/+bug/2015746>`_:
+    Fixed: minor code changes to work with new wsapi.