From 5c336123d3252e7fc4e1aeabd853457ab05838be Mon Sep 17 00:00:00 2001
From: Li Min Liu <liminliu@cn.ibm.com>
Date: Tue, 1 Apr 2014 17:08:37 +0800
Subject: [PATCH] Change iogrp property when retyping for Storwize/SVC

If need migration when retyping, Storwize/SVC driver will add a copy
of the volume first, and then start a task to check volume sync
progress which will run each 10 mins. At last delete the origin copy
when sync finished.

But iogrp property is not a parameter of addvdiskcopy, so the iogrp
of the copy volume is the same as the origin. If iogrp property is
diff between the old and new volume type, the property will not
change when retyped.

Change-Id: Ie4414bcf95fa6e61d7d618618f48837eef740da4
closed-bug: #1298247
---
 cinder/tests/test_storwize_svc.py             | 97 ++++---------------
 .../drivers/ibm/storwize_svc/__init__.py      | 12 ++-
 .../drivers/ibm/storwize_svc/helpers.py       | 21 ++--
 cinder/volume/drivers/ibm/storwize_svc/ssh.py |  8 ++
 4 files changed, 47 insertions(+), 91 deletions(-)

diff --git a/cinder/tests/test_storwize_svc.py b/cinder/tests/test_storwize_svc.py
index 79f9b9423..cce280a6d 100644
--- a/cinder/tests/test_storwize_svc.py
+++ b/cinder/tests/test_storwize_svc.py
@@ -1068,7 +1068,7 @@ port_speed!N/A
         return('FlashCopy Mapping, id [' + fcmap_info['id'] +
                '], successfully created', '')
 
-    def _cmd_gen_prestartfcmap(self, **kwargs):
+    def _cmd_prestartfcmap(self, **kwargs):
         if 'obj' not in kwargs:
             return self._errors['CMMVC5701E']
         id_num = kwargs['obj']
@@ -1084,7 +1084,7 @@ port_speed!N/A
 
         return self._state_transition('prepare', fcmap)
 
-    def _cmd_gen_startfcmap(self, **kwargs):
+    def _cmd_startfcmap(self, **kwargs):
         if 'obj' not in kwargs:
             return self._errors['CMMVC5701E']
         id_num = kwargs['obj']
@@ -1375,6 +1375,16 @@ port_speed!N/A
             vol['IO_group_name'] = iogrp
         return ('', '')
 
+    def _cmd_addvdiskaccess(self, **kwargs):
+        if 'obj' not in kwargs:
+            return self._errors['CMMVC5701E']
+        return ('', '')
+
+    def _cmd_rmvdiskaccess(self, **kwargs):
+        if 'obj' not in kwargs:
+            return self._errors['CMMVC5701E']
+        return ('', '')
+
     def _add_host_to_list(self, connector):
         host_info = {}
         host_info['id'] = self._find_unused_id(self._hosts_list)
@@ -1402,81 +1412,8 @@ port_speed!N/A
 
         command = kwargs['cmd']
         del kwargs['cmd']
-
-        if command == 'lsmdiskgrp':
-            out, err = self._cmd_lsmdiskgrp(**kwargs)
-        elif command == 'lslicense':
-            out, err = self._cmd_lslicense(**kwargs)
-        elif command == 'lssystem':
-            out, err = self._cmd_lssystem(**kwargs)
-        elif command == 'lsnodecanister':
-            out, err = self._cmd_lsnodecanister(**kwargs)
-        elif command == 'lsnode':
-            out, err = self._cmd_lsnode(**kwargs)
-        elif command == 'lsportip':
-            out, err = self._cmd_lsportip(**kwargs)
-        elif command == 'lsfabric':
-            out, err = self._cmd_lsfabric(**kwargs)
-        elif command == 'mkvdisk':
-            out, err = self._cmd_mkvdisk(**kwargs)
-        elif command == 'rmvdisk':
-            out, err = self._cmd_rmvdisk(**kwargs)
-        elif command == 'expandvdisksize':
-            out, err = self._cmd_expandvdisksize(**kwargs)
-        elif command == 'lsvdisk':
-            out, err = self._cmd_lsvdisk(**kwargs)
-        elif command == 'lsiogrp':
-            out, err = self._cmd_lsiogrp(**kwargs)
-        elif command == 'mkhost':
-            out, err = self._cmd_mkhost(**kwargs)
-        elif command == 'addhostport':
-            out, err = self._cmd_addhostport(**kwargs)
-        elif command == 'chhost':
-            out, err = self._cmd_chhost(**kwargs)
-        elif command == 'rmhost':
-            out, err = self._cmd_rmhost(**kwargs)
-        elif command == 'lshost':
-            out, err = self._cmd_lshost(**kwargs)
-        elif command == 'lsiscsiauth':
-            out, err = self._cmd_lsiscsiauth(**kwargs)
-        elif command == 'mkvdiskhostmap':
-            out, err = self._cmd_mkvdiskhostmap(**kwargs)
-        elif command == 'rmvdiskhostmap':
-            out, err = self._cmd_rmvdiskhostmap(**kwargs)
-        elif command == 'lshostvdiskmap':
-            out, err = self._cmd_lshostvdiskmap(**kwargs)
-        elif command == 'lsvdiskhostmap':
-            out, err = self._cmd_lsvdiskhostmap(**kwargs)
-        elif command == 'mkfcmap':
-            out, err = self._cmd_mkfcmap(**kwargs)
-        elif command == 'prestartfcmap':
-            out, err = self._cmd_gen_prestartfcmap(**kwargs)
-        elif command == 'startfcmap':
-            out, err = self._cmd_gen_startfcmap(**kwargs)
-        elif command == 'stopfcmap':
-            out, err = self._cmd_stopfcmap(**kwargs)
-        elif command == 'rmfcmap':
-            out, err = self._cmd_rmfcmap(**kwargs)
-        elif command == 'chfcmap':
-            out, err = self._cmd_chfcmap(**kwargs)
-        elif command == 'lsfcmap':
-            out, err = self._cmd_lsfcmap(**kwargs)
-        elif command == 'lsvdiskfcmappings':
-            out, err = self._cmd_lsvdiskfcmappings(**kwargs)
-        elif command == 'migratevdisk':
-            out, err = self._cmd_migratevdisk(**kwargs)
-        elif command == 'addvdiskcopy':
-            out, err = self._cmd_addvdiskcopy(**kwargs)
-        elif command == 'lsvdiskcopy':
-            out, err = self._cmd_lsvdiskcopy(**kwargs)
-        elif command == 'rmvdiskcopy':
-            out, err = self._cmd_rmvdiskcopy(**kwargs)
-        elif command == 'chvdisk':
-            out, err = self._cmd_chvdisk(**kwargs)
-        elif command == 'movevdisk':
-            out, err = self._cmd_movevdisk(**kwargs)
-        else:
-            out, err = ('', 'ERROR: Unsupported command')
+        func = getattr(self, '_cmd_' + command)
+        out, err = func(**kwargs)
 
         if (check_exit_code) and (len(err) != 0):
             raise processutils.ProcessExecutionError(exit_code=1,
@@ -2403,8 +2340,8 @@ class StorwizeSVCDriverTestCase(test.TestCase):
         host = {'host': 'foo', 'capabilities': cap}
         ctxt = context.get_admin_context()
 
-        key_specs_old = {'compression': True}
-        key_specs_new = {'compression': False}
+        key_specs_old = {'compression': True, 'iogrp': 0}
+        key_specs_new = {'compression': False, 'iogrp': 1}
         old_type_ref = volume_types.create(ctxt, 'old', key_specs_old)
         new_type_ref = volume_types.create(ctxt, 'new', key_specs_new)
 
@@ -2421,6 +2358,8 @@ class StorwizeSVCDriverTestCase(test.TestCase):
         self.driver.retype(ctxt, volume, new_type, diff, host)
         attrs = self.driver._helpers.get_vdisk_attributes(volume['name'])
         self.assertEqual('no', attrs['compressed_copy'])
+        self.assertEqual('1', attrs['IO_group_id'], 'Volume retype '
+                         'failed')
         self.driver.delete_volume(volume)
 
     def test_set_storage_code_level_success(self):
diff --git a/cinder/volume/drivers/ibm/storwize_svc/__init__.py b/cinder/volume/drivers/ibm/storwize_svc/__init__.py
index e676965f2..eb0f58955 100644
--- a/cinder/volume/drivers/ibm/storwize_svc/__init__.py
+++ b/cinder/volume/drivers/ibm/storwize_svc/__init__.py
@@ -703,7 +703,7 @@ class StorwizeSVCDriver(san.SanDriver):
                                                        'host': host})
 
         ignore_keys = ['protocol', 'multipath']
-        no_copy_keys = ['warning', 'autoexpand', 'easytier', 'iogrp']
+        no_copy_keys = ['warning', 'autoexpand', 'easytier']
         copy_keys = ['rsize', 'grainsize', 'compression']
         all_keys = ignore_keys + no_copy_keys + copy_keys
         old_opts = self._get_vdisk_params(volume['volume_type_id'])
@@ -729,11 +729,21 @@ class StorwizeSVCDriver(san.SanDriver):
             if dest_pool is None:
                 return False
 
+            if old_opts['iogrp'] != new_opts['iogrp']:
+                self._helpers.change_vdisk_iogrp(volume['name'], self._state,
+                                                 (new_opts['iogrp'],
+                                                  old_opts['iogrp']))
+
             new_op = self._helpers.add_vdisk_copy(volume['name'], dest_pool,
                                                   new_type, self._state,
                                                   self.configuration)
             self._add_vdisk_copy_op(ctxt, volume, new_op)
         else:
+            if old_opts['iogrp'] != new_opts['iogrp']:
+                self._helpers.change_vdisk_iogrp(volume['name'], self._state,
+                                                 (new_opts['iogrp'],
+                                                  old_opts['iogrp']))
+
             self._helpers.change_vdisk_options(volume['name'], vdisk_changes,
                                                new_opts, self._state)
 
diff --git a/cinder/volume/drivers/ibm/storwize_svc/helpers.py b/cinder/volume/drivers/ibm/storwize_svc/helpers.py
index 860382991..b973c4584 100644
--- a/cinder/volume/drivers/ibm/storwize_svc/helpers.py
+++ b/cinder/volume/drivers/ibm/storwize_svc/helpers.py
@@ -726,8 +726,6 @@ class StorwizeHelpers(object):
         return dest_pool
 
     def change_vdisk_options(self, vdisk, changes, opts, state):
-        if 'iogrp' in opts:
-            opts['iogrp'] = str(opts['iogrp'])
         if 'warning' in opts:
             opts['warning'] = '%s%%' % str(opts['warning'])
         if 'easytier' in opts:
@@ -735,18 +733,19 @@ class StorwizeHelpers(object):
         if 'autoexpand' in opts:
             opts['autoexpand'] = 'on' if opts['autoexpand'] else 'off'
 
-        if 'iogrp' in changes:
-            changes.remove('iogrp')
-            if state['code_level'] < (6, 4, 0, 0):
-                LOG.debug(_('Ignore change IO group as storage code level '
-                            'is %(code_level)s, below then '
-                            '6.4.0.0') % {'code_level': state['code_level']})
-            else:
-                self.ssh.movevdisk(vdisk, opts['iogrp'])
-
         for key in changes:
             self.ssh.chvdisk(vdisk, ['-' + key, opts[key]])
 
+    def change_vdisk_iogrp(self, vdisk, state, iogrp):
+        if state['code_level'] < (6, 4, 0, 0):
+            LOG.debug(_('Ignore change IO group as storage code level is '
+                        '%(code_level)s, below the required 6.4.0.0') %
+                      {'code_level': state['code_level']})
+        else:
+            self.ssh.movevdisk(vdisk, str(iogrp[0]))
+            self.ssh.addvdiskaccess(vdisk, str(iogrp[0]))
+            self.ssh.rmvdiskaccess(vdisk, str(iogrp[1]))
+
     def vdisk_by_uid(self, vdisk_uid):
         """Returns the properties of the vdisk with the specified UID.
 
diff --git a/cinder/volume/drivers/ibm/storwize_svc/ssh.py b/cinder/volume/drivers/ibm/storwize_svc/ssh.py
index fda74568d..0948384ce 100644
--- a/cinder/volume/drivers/ibm/storwize_svc/ssh.py
+++ b/cinder/volume/drivers/ibm/storwize_svc/ssh.py
@@ -316,6 +316,14 @@ class StorwizeSSH(object):
         ssh_cmd = ['svctask', 'rmvdiskcopy', '-copy', copy_id, vdisk]
         self.run_ssh_assert_no_output(ssh_cmd)
 
+    def addvdiskaccess(self, vdisk, iogrp):
+        ssh_cmd = ['svctask', 'addvdiskaccess', '-iogrp', iogrp, vdisk]
+        self.run_ssh_assert_no_output(ssh_cmd)
+
+    def rmvdiskaccess(self, vdisk, iogrp):
+        ssh_cmd = ['svctask', 'rmvdiskaccess', '-iogrp', iogrp, vdisk]
+        self.run_ssh_assert_no_output(ssh_cmd)
+
 
 class CLIResponse(object):
     '''Parse SVC CLI output and generate iterable.'''
-- 
2.45.2