We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
vPool GUI work
- Add vPool wizard - Step 1
  - [x]  Remove backend type selection
    -Add vPool wizard - Step 2
  - [x] "Fragment Cache" should become "Cache"
  - [x] "Place Fragment Cache on disk" should be "Use local disk"
  - [x] "Use another ALBA Backend as Fragment Cache" should be "Use another Backend Cache"
- Add vPool wizard - Step 3
  - [x] Replace "StorageDriver Caching Information" by "Storage Driver Write Buffer"
  - [x] Remove Strategy
  - [x] Remove Deduplication
- Add vPool wizard - Step 4
  - [x]  https://github.com/openvstorage/framework/issues/783
- vPool overview page
  - [x] Remove Type, Connection and Login and replace by OVS Backend & preset
- vPool detail page
  - [x] Add backend info https://github.com/openvstorage/framework/issues/735
  - [x] Under configuration remove "Cache strategy", "Dedupe Mode"
  - [x] Under Mgmt actions add a link to the accelerated ALBA for each storage router (link to the backend)
  - [x] Under Mgmt actions make the Storage routers clickable

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ovs/dal/migration/ovsmigrator.py`
Content:
```
1 # Copyright (C) 2016 iNuron NV
2 #
3 # This file is part of Open vStorage Open Source Edition (OSE),
4 # as available from
5 #
6 #      http://www.openvstorage.org and
7 #      http://www.openvstorage.com.
8 #
9 # This file is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)
11 # as published by the Free Software Foundation, in version 3 as it comes
12 # in the LICENSE.txt file of the Open vStorage OSE distribution.
13 #
14 # Open vStorage is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY of any kind.
16 
17 """
18 OVS migration module
19 """
20 
21 import hashlib
22 import random
23 import string
24 
25 
26 class OVSMigrator(object):
27     """
28     Handles all model related migrations
29     """
30 
31     identifier = 'ovs'
32     THIS_VERSION = 11
33 
34     def __init__(self):
35         """ Init method """
36         pass
37 
38     @staticmethod
39     def migrate(previous_version):
40         """
41         Migrates from a given version to the current version. It uses 'previous_version' to be smart
42         wherever possible, but the code should be able to migrate any version towards the expected version.
43         When this is not possible, the code can set a minimum version and raise when it is not met.
44         :param previous_version: The previous version from which to start the migration
45         :type previous_version: float
46         """
47 
48         working_version = previous_version
49 
50         if working_version == 0:
51             # Initial version:
52             # * Set the version to THIS RELEASE version
53 
54             from ovs.dal.hybrids.user import User
55             from ovs.dal.hybrids.group import Group
56             from ovs.dal.hybrids.role import Role
57             from ovs.dal.hybrids.client import Client
58             from ovs.dal.hybrids.j_rolegroup import RoleGroup
59             from ovs.dal.hybrids.j_roleclient import RoleClient
60             from ovs.dal.hybrids.backendtype import BackendType
61             from ovs.dal.hybrids.servicetype import ServiceType
62             from ovs.dal.hybrids.branding import Branding
63             from ovs.dal.lists.backendtypelist import BackendTypeList
64 
65             # Create groups
66             admin_group = Group()
67             admin_group.name = 'administrators'
68             admin_group.description = 'Administrators'
69             admin_group.save()
70             viewers_group = Group()
71             viewers_group.name = 'viewers'
72             viewers_group.description = 'Viewers'
73             viewers_group.save()
74 
75             # Create users
76             admin = User()
77             admin.username = 'admin'
78             admin.password = hashlib.sha256('admin').hexdigest()
79             admin.is_active = True
80             admin.group = admin_group
81             admin.save()
82 
83             # Create internal OAuth 2 clients
84             admin_pw_client = Client()
85             admin_pw_client.ovs_type = 'INTERNAL'
86             admin_pw_client.grant_type = 'PASSWORD'
87             admin_pw_client.user = admin
88             admin_pw_client.save()
89             admin_cc_client = Client()
90             admin_cc_client.ovs_type = 'INTERNAL'
91             admin_cc_client.grant_type = 'CLIENT_CREDENTIALS'
92             admin_cc_client.client_secret = ''.join(random.choice(string.ascii_letters +
93                                                                   string.digits +
94                                                                   '|_=+*#@!/-[]{}<>.?,\'";:~')
95                                                     for _ in range(128))
96             admin_cc_client.user = admin
97             admin_cc_client.save()
98 
99             # Create roles
100             read_role = Role()
101             read_role.code = 'read'
102             read_role.name = 'Read'
103             read_role.description = 'Can read objects'
104             read_role.save()
105             write_role = Role()
106             write_role.code = 'write'
107             write_role.name = 'Write'
108             write_role.description = 'Can write objects'
109             write_role.save()
110             manage_role = Role()
111             manage_role.code = 'manage'
112             manage_role.name = 'Manage'
113             manage_role.description = 'Can manage the system'
114             manage_role.save()
115 
116             # Attach groups to roles
117             mapping = [
118                 (admin_group, [read_role, write_role, manage_role]),
119                 (viewers_group, [read_role])
120             ]
121             for setting in mapping:
122                 for role in setting[1]:
123                     rolegroup = RoleGroup()
124                     rolegroup.group = setting[0]
125                     rolegroup.role = role
126                     rolegroup.save()
127                 for user in setting[0].users:
128                     for role in setting[1]:
129                         for client in user.clients:
130                             roleclient = RoleClient()
131                             roleclient.client = client
132                             roleclient.role = role
133                             roleclient.save()
134 
135             # Add service types
136             for service_type_info in [ServiceType.SERVICE_TYPES.MD_SERVER, ServiceType.SERVICE_TYPES.ALBA_PROXY, ServiceType.SERVICE_TYPES.ARAKOON]:
137                 service_type = ServiceType()
138                 service_type.name = service_type_info
139                 service_type.save()
140 
141             # Branding
142             branding = Branding()
143             branding.name = 'Default'
144             branding.description = 'Default bootstrap theme'
145             branding.css = 'bootstrap-default.min.css'
146             branding.productname = 'Open vStorage'
147             branding.is_default = True
148             branding.save()
149             slate = Branding()
150             slate.name = 'Slate'
151             slate.description = 'Dark bootstrap theme'
152             slate.css = 'bootstrap-slate.min.css'
153             slate.productname = 'Open vStorage'
154             slate.is_default = False
155             slate.save()
156 
157         # From here on, all actual migration should happen to get to the expected state for THIS RELEASE
158         elif working_version < OVSMigrator.THIS_VERSION:
159             # Migrate unique constraints
160             from ovs.dal.helpers import HybridRunner, Descriptor
161             from ovs.extensions.storage.persistentfactory import PersistentFactory
162             client = PersistentFactory.get_client()
163             hybrid_structure = HybridRunner.get_hybrids()
164             for class_descriptor in hybrid_structure.values():
165                 cls = Descriptor().load(class_descriptor).get_object()
166                 classname = cls.__name__.lower()
167                 unique_key = 'ovs_unique_{0}_{{0}}_'.format(classname)
168                 uniques = []
169                 # noinspection PyProtectedMember
170                 for prop in cls._properties:
171                     if prop.unique is True and len([k for k in client.prefix(unique_key.format(prop.name))]) == 0:
172                         uniques.append(prop.name)
173                 if len(uniques) > 0:
174                     prefix = 'ovs_data_{0}_'.format(classname)
175                     for key in client.prefix(prefix):
176                         data = client.get(key)
177                         for property_name in uniques:
178                             ukey = '{0}{1}'.format(unique_key.format(property_name), hashlib.sha1(str(data[property_name])).hexdigest())
179                             client.set(ukey, key)
180 
181             # Complete rework of the way we detect devices to assign roles or use as ASD
182             # Allow loop-, raid-, nvme-, ??-devices and logical volumes as ASD (https://github.com/openvstorage/framework/issues/792)
183             from ovs.dal.lists.storagerouterlist import StorageRouterList
184             from ovs.extensions.generic.sshclient import SSHClient, UnableToConnectException
185             from ovs.lib.disk import DiskController
186 
187             for storagerouter in StorageRouterList.get_storagerouters():
188                 try:
189                     client = SSHClient(storagerouter, username='root')
190                 except UnableToConnectException:
191                     raise
192 
193                 # Retrieve all symlinks for all devices
194                 # Example of name_alias_mapping:
195                 # {'/dev/md0': ['/dev/disk/by-id/md-uuid-ad2de634:26d97253:5eda0a23:96986b76', '/dev/disk/by-id/md-name-OVS-1:0'],
196                 #  '/dev/sda': ['/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0'],
197                 #  '/dev/sda1': ['/dev/disk/by-uuid/e3e0bc62-4edc-4c6b-a6ce-1f39e8f27e41', '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0-part1']}
198                 name_alias_mapping = {}
199                 alias_name_mapping = {}
200                 for path_type in client.dir_list(directory='/dev/disk'):
201                     if path_type in ['by-uuid', 'by-partuuid']:  # UUIDs can change after creating a filesystem on a partition
202                         continue
203                     directory = '/dev/disk/{0}'.format(path_type)
204                     for symlink in client.dir_list(directory=directory):
205                         symlink_path = '{0}/{1}'.format(directory, symlink)
206                         link = client.file_read_link(symlink_path)
207                         if link not in name_alias_mapping:
208                             name_alias_mapping[link] = []
209                         name_alias_mapping[link].append(symlink_path)
210                         alias_name_mapping[symlink_path] = link
211 
212                 for disk in storagerouter.disks:
213                     if disk.aliases is None:
214                         # noinspection PyProtectedMember
215                         device_path = '/dev/{0}'.format(disk.name)
216                         disk.aliases = name_alias_mapping.get(device_path, [device_path])
217                         disk.save()
218                     for partition in disk.partitions:
219                         # noinspection PyProtectedMember
220                         partition_device = alias_name_mapping.get(partition._data['path'])
221                         if partition.aliases is None:
222                             if partition_device is None:
223                                 partition.aliases = []
224                                 partition.save()
225                                 continue
226                             partition.aliases = name_alias_mapping.get(partition_device, [])
227                             partition.save()
228 
229                 DiskController.sync_with_reality(storagerouter_guid=storagerouter.guid)
230 
231             # Only support ALBA backend type
232             from ovs.dal.lists.backendtypelist import BackendTypeList
233             for backend_type in BackendTypeList.get_backend_types():
234                 if backend_type.code != 'alba':
235                     backend_type.delete()
236 
237             # Reformat the vpool.metadata information
238             from ovs.dal.lists.vpoollist import VPoolList
239             for vpool in VPoolList.get_vpools():
240                 new_metadata = {}
241                 for metadata_key, value in vpool.metadata.items():
242                     new_info = {}
243                     storagerouter_guids = [key for key in vpool.metadata.keys() if not key.startswith('backend')]
244                     if isinstance(value, dict):
245                         read_cache = value.get('backend_info', {}).get('fragment_cache_on_read', True)
246                         write_cache = value.get('backend_info', {}).get('fragment_cache_on_write', False)
247                         new_info['backend_info'] = {'alba_backend_guid': value.get('backend_guid'),
248                                                     'backend_guid': None,
249                                                     'frag_size': value.get('backend_info', {}).get('frag_size'),
250                                                     'name': value.get('name'),
251                                                     'policies': value.get('backend_info', {}).get('policies'),
252                                                     'preset': value.get('preset'),
253                                                     'sco_size': value.get('backend_info', {}).get('sco_size'),
254                                                     'total_size': value.get('backend_info', {}).get('total_size')}
255                         new_info['arakoon_config'] = value.get('arakoon_config')
256                         new_info['connection_info'] = {'host': value.get('connection', {}).get('host', ''),
257                                                        'port': value.get('connection', {}).get('port', ''),
258                                                        'local': value.get('connection', {}).get('local', ''),
259                                                        'client_id': value.get('connection', {}).get('client_id', ''),
260                                                        'client_secret': value.get('connection', {}).get('client_secret', '')}
261                         if metadata_key == 'backend':
262                             new_info['caching_info'] = dict((sr_guid, {'fragment_cache_on_read': read_cache, 'fragment_cache_on_write': write_cache}) for sr_guid in storagerouter_guids)
263                     if metadata_key in storagerouter_guids:
264                         metadata_key = 'backend_aa_{0}'.format(metadata_key)
265                     new_metadata[metadata_key] = new_info
266                 vpool.metadata = new_metadata
267                 vpool.save()
268 
269         return OVSMigrator.THIS_VERSION
270
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ovs/dal/migration/ovsmigrator.py b/ovs/dal/migration/ovsmigrator.py
--- a/ovs/dal/migration/ovsmigrator.py
+++ b/ovs/dal/migration/ovsmigrator.py
@@ -57,7 +57,6 @@
             from ovs.dal.hybrids.client import Client
             from ovs.dal.hybrids.j_rolegroup import RoleGroup
             from ovs.dal.hybrids.j_roleclient import RoleClient
-            from ovs.dal.hybrids.backendtype import BackendType
             from ovs.dal.hybrids.servicetype import ServiceType
             from ovs.dal.hybrids.branding import Branding
             from ovs.dal.lists.backendtypelist import BackendTypeList
@@ -266,4 +265,11 @@
                 vpool.metadata = new_metadata
                 vpool.save()
 
+            # Removal of READ role
+            from ovs.dal.lists.diskpartitionlist import DiskPartitionList
+            for partition in DiskPartitionList.get_partitions():
+                if 'READ' in partition.roles:
+                    partition.roles.remove('READ')
+                    partition.save()
+
         return OVSMigrator.THIS_VERSION

{"golden_diff": "diff --git a/ovs/dal/migration/ovsmigrator.py b/ovs/dal/migration/ovsmigrator.py\n--- a/ovs/dal/migration/ovsmigrator.py\n+++ b/ovs/dal/migration/ovsmigrator.py\n@@ -57,7 +57,6 @@\n             from ovs.dal.hybrids.client import Client\n             from ovs.dal.hybrids.j_rolegroup import RoleGroup\n             from ovs.dal.hybrids.j_roleclient import RoleClient\n-            from ovs.dal.hybrids.backendtype import BackendType\n             from ovs.dal.hybrids.servicetype import ServiceType\n             from ovs.dal.hybrids.branding import Branding\n             from ovs.dal.lists.backendtypelist import BackendTypeList\n@@ -266,4 +265,11 @@\n                 vpool.metadata = new_metadata\n                 vpool.save()\n \n+            # Removal of READ role\n+            from ovs.dal.lists.diskpartitionlist import DiskPartitionList\n+            for partition in DiskPartitionList.get_partitions():\n+                if 'READ' in partition.roles:\n+                    partition.roles.remove('READ')\n+                    partition.save()\n+\n         return OVSMigrator.THIS_VERSION\n", "issue": "vPool GUI work\n- Add vPool wizard - Step 1\r\n  - [x]  Remove backend type selection\r\n    -Add vPool wizard - Step 2\r\n  - [x] \"Fragment Cache\" should become \"Cache\"\r\n  - [x] \"Place Fragment Cache on disk\" should be \"Use local disk\"\r\n  - [x] \"Use another ALBA Backend as Fragment Cache\" should be \"Use another Backend Cache\"\r\n- Add vPool wizard - Step 3\r\n  - [x] Replace \"StorageDriver Caching Information\" by \"Storage Driver Write Buffer\"\r\n  - [x] Remove Strategy\r\n  - [x] Remove Deduplication\r\n- Add vPool wizard - Step 4\r\n  - [x]  https://github.com/openvstorage/framework/issues/783\r\n- vPool overview page\r\n  - [x] Remove Type, Connection and Login and replace by OVS Backend & preset\r\n- vPool detail page\r\n  - [x] Add backend info https://github.com/openvstorage/framework/issues/735\r\n  - [x] Under configuration remove \"Cache strategy\", \"Dedupe Mode\"\r\n  - [x] Under Mgmt actions add a link to the accelerated ALBA for each storage router (link to the backend)\r\n  - [x] Under Mgmt actions make the Storage routers clickable\n", "before_files": [{"content": "# Copyright (C) 2016 iNuron NV\n#\n# This file is part of Open vStorage Open Source Edition (OSE),\n# as available from\n#\n#      http://www.openvstorage.org and\n#      http://www.openvstorage.com.\n#\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)\n# as published by the Free Software Foundation, in version 3 as it comes\n# in the LICENSE.txt file of the Open vStorage OSE distribution.\n#\n# Open vStorage is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY of any kind.\n\n\"\"\"\nOVS migration module\n\"\"\"\n\nimport hashlib\nimport random\nimport string\n\n\nclass OVSMigrator(object):\n    \"\"\"\n    Handles all model related migrations\n    \"\"\"\n\n    identifier = 'ovs'\n    THIS_VERSION = 11\n\n    def __init__(self):\n        \"\"\" Init method \"\"\"\n        pass\n\n    @staticmethod\n    def migrate(previous_version):\n        \"\"\"\n        Migrates from a given version to the current version. It uses 'previous_version' to be smart\n        wherever possible, but the code should be able to migrate any version towards the expected version.\n        When this is not possible, the code can set a minimum version and raise when it is not met.\n        :param previous_version: The previous version from which to start the migration\n        :type previous_version: float\n        \"\"\"\n\n        working_version = previous_version\n\n        if working_version == 0:\n            # Initial version:\n            # * Set the version to THIS RELEASE version\n\n            from ovs.dal.hybrids.user import User\n            from ovs.dal.hybrids.group import Group\n            from ovs.dal.hybrids.role import Role\n            from ovs.dal.hybrids.client import Client\n            from ovs.dal.hybrids.j_rolegroup import RoleGroup\n            from ovs.dal.hybrids.j_roleclient import RoleClient\n            from ovs.dal.hybrids.backendtype import BackendType\n            from ovs.dal.hybrids.servicetype import ServiceType\n            from ovs.dal.hybrids.branding import Branding\n            from ovs.dal.lists.backendtypelist import BackendTypeList\n\n            # Create groups\n            admin_group = Group()\n            admin_group.name = 'administrators'\n            admin_group.description = 'Administrators'\n            admin_group.save()\n            viewers_group = Group()\n            viewers_group.name = 'viewers'\n            viewers_group.description = 'Viewers'\n            viewers_group.save()\n\n            # Create users\n            admin = User()\n            admin.username = 'admin'\n            admin.password = hashlib.sha256('admin').hexdigest()\n            admin.is_active = True\n            admin.group = admin_group\n            admin.save()\n\n            # Create internal OAuth 2 clients\n            admin_pw_client = Client()\n            admin_pw_client.ovs_type = 'INTERNAL'\n            admin_pw_client.grant_type = 'PASSWORD'\n            admin_pw_client.user = admin\n            admin_pw_client.save()\n            admin_cc_client = Client()\n            admin_cc_client.ovs_type = 'INTERNAL'\n            admin_cc_client.grant_type = 'CLIENT_CREDENTIALS'\n            admin_cc_client.client_secret = ''.join(random.choice(string.ascii_letters +\n                                                                  string.digits +\n                                                                  '|_=+*#@!/-[]{}<>.?,\\'\";:~')\n                                                    for _ in range(128))\n            admin_cc_client.user = admin\n            admin_cc_client.save()\n\n            # Create roles\n            read_role = Role()\n            read_role.code = 'read'\n            read_role.name = 'Read'\n            read_role.description = 'Can read objects'\n            read_role.save()\n            write_role = Role()\n            write_role.code = 'write'\n            write_role.name = 'Write'\n            write_role.description = 'Can write objects'\n            write_role.save()\n            manage_role = Role()\n            manage_role.code = 'manage'\n            manage_role.name = 'Manage'\n            manage_role.description = 'Can manage the system'\n            manage_role.save()\n\n            # Attach groups to roles\n            mapping = [\n                (admin_group, [read_role, write_role, manage_role]),\n                (viewers_group, [read_role])\n            ]\n            for setting in mapping:\n                for role in setting[1]:\n                    rolegroup = RoleGroup()\n                    rolegroup.group = setting[0]\n                    rolegroup.role = role\n                    rolegroup.save()\n                for user in setting[0].users:\n                    for role in setting[1]:\n                        for client in user.clients:\n                            roleclient = RoleClient()\n                            roleclient.client = client\n                            roleclient.role = role\n                            roleclient.save()\n\n            # Add service types\n            for service_type_info in [ServiceType.SERVICE_TYPES.MD_SERVER, ServiceType.SERVICE_TYPES.ALBA_PROXY, ServiceType.SERVICE_TYPES.ARAKOON]:\n                service_type = ServiceType()\n                service_type.name = service_type_info\n                service_type.save()\n\n            # Branding\n            branding = Branding()\n            branding.name = 'Default'\n            branding.description = 'Default bootstrap theme'\n            branding.css = 'bootstrap-default.min.css'\n            branding.productname = 'Open vStorage'\n            branding.is_default = True\n            branding.save()\n            slate = Branding()\n            slate.name = 'Slate'\n            slate.description = 'Dark bootstrap theme'\n            slate.css = 'bootstrap-slate.min.css'\n            slate.productname = 'Open vStorage'\n            slate.is_default = False\n            slate.save()\n\n        # From here on, all actual migration should happen to get to the expected state for THIS RELEASE\n        elif working_version < OVSMigrator.THIS_VERSION:\n            # Migrate unique constraints\n            from ovs.dal.helpers import HybridRunner, Descriptor\n            from ovs.extensions.storage.persistentfactory import PersistentFactory\n            client = PersistentFactory.get_client()\n            hybrid_structure = HybridRunner.get_hybrids()\n            for class_descriptor in hybrid_structure.values():\n                cls = Descriptor().load(class_descriptor).get_object()\n                classname = cls.__name__.lower()\n                unique_key = 'ovs_unique_{0}_{{0}}_'.format(classname)\n                uniques = []\n                # noinspection PyProtectedMember\n                for prop in cls._properties:\n                    if prop.unique is True and len([k for k in client.prefix(unique_key.format(prop.name))]) == 0:\n                        uniques.append(prop.name)\n                if len(uniques) > 0:\n                    prefix = 'ovs_data_{0}_'.format(classname)\n                    for key in client.prefix(prefix):\n                        data = client.get(key)\n                        for property_name in uniques:\n                            ukey = '{0}{1}'.format(unique_key.format(property_name), hashlib.sha1(str(data[property_name])).hexdigest())\n                            client.set(ukey, key)\n\n            # Complete rework of the way we detect devices to assign roles or use as ASD\n            # Allow loop-, raid-, nvme-, ??-devices and logical volumes as ASD (https://github.com/openvstorage/framework/issues/792)\n            from ovs.dal.lists.storagerouterlist import StorageRouterList\n            from ovs.extensions.generic.sshclient import SSHClient, UnableToConnectException\n            from ovs.lib.disk import DiskController\n\n            for storagerouter in StorageRouterList.get_storagerouters():\n                try:\n                    client = SSHClient(storagerouter, username='root')\n                except UnableToConnectException:\n                    raise\n\n                # Retrieve all symlinks for all devices\n                # Example of name_alias_mapping:\n                # {'/dev/md0': ['/dev/disk/by-id/md-uuid-ad2de634:26d97253:5eda0a23:96986b76', '/dev/disk/by-id/md-name-OVS-1:0'],\n                #  '/dev/sda': ['/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0'],\n                #  '/dev/sda1': ['/dev/disk/by-uuid/e3e0bc62-4edc-4c6b-a6ce-1f39e8f27e41', '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0-part1']}\n                name_alias_mapping = {}\n                alias_name_mapping = {}\n                for path_type in client.dir_list(directory='/dev/disk'):\n                    if path_type in ['by-uuid', 'by-partuuid']:  # UUIDs can change after creating a filesystem on a partition\n                        continue\n                    directory = '/dev/disk/{0}'.format(path_type)\n                    for symlink in client.dir_list(directory=directory):\n                        symlink_path = '{0}/{1}'.format(directory, symlink)\n                        link = client.file_read_link(symlink_path)\n                        if link not in name_alias_mapping:\n                            name_alias_mapping[link] = []\n                        name_alias_mapping[link].append(symlink_path)\n                        alias_name_mapping[symlink_path] = link\n\n                for disk in storagerouter.disks:\n                    if disk.aliases is None:\n                        # noinspection PyProtectedMember\n                        device_path = '/dev/{0}'.format(disk.name)\n                        disk.aliases = name_alias_mapping.get(device_path, [device_path])\n                        disk.save()\n                    for partition in disk.partitions:\n                        # noinspection PyProtectedMember\n                        partition_device = alias_name_mapping.get(partition._data['path'])\n                        if partition.aliases is None:\n                            if partition_device is None:\n                                partition.aliases = []\n                                partition.save()\n                                continue\n                            partition.aliases = name_alias_mapping.get(partition_device, [])\n                            partition.save()\n\n                DiskController.sync_with_reality(storagerouter_guid=storagerouter.guid)\n\n            # Only support ALBA backend type\n            from ovs.dal.lists.backendtypelist import BackendTypeList\n            for backend_type in BackendTypeList.get_backend_types():\n                if backend_type.code != 'alba':\n                    backend_type.delete()\n\n            # Reformat the vpool.metadata information\n            from ovs.dal.lists.vpoollist import VPoolList\n            for vpool in VPoolList.get_vpools():\n                new_metadata = {}\n                for metadata_key, value in vpool.metadata.items():\n                    new_info = {}\n                    storagerouter_guids = [key for key in vpool.metadata.keys() if not key.startswith('backend')]\n                    if isinstance(value, dict):\n                        read_cache = value.get('backend_info', {}).get('fragment_cache_on_read', True)\n                        write_cache = value.get('backend_info', {}).get('fragment_cache_on_write', False)\n                        new_info['backend_info'] = {'alba_backend_guid': value.get('backend_guid'),\n                                                    'backend_guid': None,\n                                                    'frag_size': value.get('backend_info', {}).get('frag_size'),\n                                                    'name': value.get('name'),\n                                                    'policies': value.get('backend_info', {}).get('policies'),\n                                                    'preset': value.get('preset'),\n                                                    'sco_size': value.get('backend_info', {}).get('sco_size'),\n                                                    'total_size': value.get('backend_info', {}).get('total_size')}\n                        new_info['arakoon_config'] = value.get('arakoon_config')\n                        new_info['connection_info'] = {'host': value.get('connection', {}).get('host', ''),\n                                                       'port': value.get('connection', {}).get('port', ''),\n                                                       'local': value.get('connection', {}).get('local', ''),\n                                                       'client_id': value.get('connection', {}).get('client_id', ''),\n                                                       'client_secret': value.get('connection', {}).get('client_secret', '')}\n                        if metadata_key == 'backend':\n                            new_info['caching_info'] = dict((sr_guid, {'fragment_cache_on_read': read_cache, 'fragment_cache_on_write': write_cache}) for sr_guid in storagerouter_guids)\n                    if metadata_key in storagerouter_guids:\n                        metadata_key = 'backend_aa_{0}'.format(metadata_key)\n                    new_metadata[metadata_key] = new_info\n                vpool.metadata = new_metadata\n                vpool.save()\n\n        return OVSMigrator.THIS_VERSION\n", "path": "ovs/dal/migration/ovsmigrator.py"}], "after_files": [{"content": "# Copyright (C) 2016 iNuron NV\n#\n# This file is part of Open vStorage Open Source Edition (OSE),\n# as available from\n#\n#      http://www.openvstorage.org and\n#      http://www.openvstorage.com.\n#\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)\n# as published by the Free Software Foundation, in version 3 as it comes\n# in the LICENSE.txt file of the Open vStorage OSE distribution.\n#\n# Open vStorage is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY of any kind.\n\n\"\"\"\nOVS migration module\n\"\"\"\n\nimport hashlib\nimport random\nimport string\n\n\nclass OVSMigrator(object):\n    \"\"\"\n    Handles all model related migrations\n    \"\"\"\n\n    identifier = 'ovs'\n    THIS_VERSION = 11\n\n    def __init__(self):\n        \"\"\" Init method \"\"\"\n        pass\n\n    @staticmethod\n    def migrate(previous_version):\n        \"\"\"\n        Migrates from a given version to the current version. It uses 'previous_version' to be smart\n        wherever possible, but the code should be able to migrate any version towards the expected version.\n        When this is not possible, the code can set a minimum version and raise when it is not met.\n        :param previous_version: The previous version from which to start the migration\n        :type previous_version: float\n        \"\"\"\n\n        working_version = previous_version\n\n        if working_version == 0:\n            # Initial version:\n            # * Set the version to THIS RELEASE version\n\n            from ovs.dal.hybrids.user import User\n            from ovs.dal.hybrids.group import Group\n            from ovs.dal.hybrids.role import Role\n            from ovs.dal.hybrids.client import Client\n            from ovs.dal.hybrids.j_rolegroup import RoleGroup\n            from ovs.dal.hybrids.j_roleclient import RoleClient\n            from ovs.dal.hybrids.servicetype import ServiceType\n            from ovs.dal.hybrids.branding import Branding\n            from ovs.dal.lists.backendtypelist import BackendTypeList\n\n            # Create groups\n            admin_group = Group()\n            admin_group.name = 'administrators'\n            admin_group.description = 'Administrators'\n            admin_group.save()\n            viewers_group = Group()\n            viewers_group.name = 'viewers'\n            viewers_group.description = 'Viewers'\n            viewers_group.save()\n\n            # Create users\n            admin = User()\n            admin.username = 'admin'\n            admin.password = hashlib.sha256('admin').hexdigest()\n            admin.is_active = True\n            admin.group = admin_group\n            admin.save()\n\n            # Create internal OAuth 2 clients\n            admin_pw_client = Client()\n            admin_pw_client.ovs_type = 'INTERNAL'\n            admin_pw_client.grant_type = 'PASSWORD'\n            admin_pw_client.user = admin\n            admin_pw_client.save()\n            admin_cc_client = Client()\n            admin_cc_client.ovs_type = 'INTERNAL'\n            admin_cc_client.grant_type = 'CLIENT_CREDENTIALS'\n            admin_cc_client.client_secret = ''.join(random.choice(string.ascii_letters +\n                                                                  string.digits +\n                                                                  '|_=+*#@!/-[]{}<>.?,\\'\";:~')\n                                                    for _ in range(128))\n            admin_cc_client.user = admin\n            admin_cc_client.save()\n\n            # Create roles\n            read_role = Role()\n            read_role.code = 'read'\n            read_role.name = 'Read'\n            read_role.description = 'Can read objects'\n            read_role.save()\n            write_role = Role()\n            write_role.code = 'write'\n            write_role.name = 'Write'\n            write_role.description = 'Can write objects'\n            write_role.save()\n            manage_role = Role()\n            manage_role.code = 'manage'\n            manage_role.name = 'Manage'\n            manage_role.description = 'Can manage the system'\n            manage_role.save()\n\n            # Attach groups to roles\n            mapping = [\n                (admin_group, [read_role, write_role, manage_role]),\n                (viewers_group, [read_role])\n            ]\n            for setting in mapping:\n                for role in setting[1]:\n                    rolegroup = RoleGroup()\n                    rolegroup.group = setting[0]\n                    rolegroup.role = role\n                    rolegroup.save()\n                for user in setting[0].users:\n                    for role in setting[1]:\n                        for client in user.clients:\n                            roleclient = RoleClient()\n                            roleclient.client = client\n                            roleclient.role = role\n                            roleclient.save()\n\n            # Add service types\n            for service_type_info in [ServiceType.SERVICE_TYPES.MD_SERVER, ServiceType.SERVICE_TYPES.ALBA_PROXY, ServiceType.SERVICE_TYPES.ARAKOON]:\n                service_type = ServiceType()\n                service_type.name = service_type_info\n                service_type.save()\n\n            # Branding\n            branding = Branding()\n            branding.name = 'Default'\n            branding.description = 'Default bootstrap theme'\n            branding.css = 'bootstrap-default.min.css'\n            branding.productname = 'Open vStorage'\n            branding.is_default = True\n            branding.save()\n            slate = Branding()\n            slate.name = 'Slate'\n            slate.description = 'Dark bootstrap theme'\n            slate.css = 'bootstrap-slate.min.css'\n            slate.productname = 'Open vStorage'\n            slate.is_default = False\n            slate.save()\n\n        # From here on, all actual migration should happen to get to the expected state for THIS RELEASE\n        elif working_version < OVSMigrator.THIS_VERSION:\n            # Migrate unique constraints\n            from ovs.dal.helpers import HybridRunner, Descriptor\n            from ovs.extensions.storage.persistentfactory import PersistentFactory\n            client = PersistentFactory.get_client()\n            hybrid_structure = HybridRunner.get_hybrids()\n            for class_descriptor in hybrid_structure.values():\n                cls = Descriptor().load(class_descriptor).get_object()\n                classname = cls.__name__.lower()\n                unique_key = 'ovs_unique_{0}_{{0}}_'.format(classname)\n                uniques = []\n                # noinspection PyProtectedMember\n                for prop in cls._properties:\n                    if prop.unique is True and len([k for k in client.prefix(unique_key.format(prop.name))]) == 0:\n                        uniques.append(prop.name)\n                if len(uniques) > 0:\n                    prefix = 'ovs_data_{0}_'.format(classname)\n                    for key in client.prefix(prefix):\n                        data = client.get(key)\n                        for property_name in uniques:\n                            ukey = '{0}{1}'.format(unique_key.format(property_name), hashlib.sha1(str(data[property_name])).hexdigest())\n                            client.set(ukey, key)\n\n            # Complete rework of the way we detect devices to assign roles or use as ASD\n            # Allow loop-, raid-, nvme-, ??-devices and logical volumes as ASD (https://github.com/openvstorage/framework/issues/792)\n            from ovs.dal.lists.storagerouterlist import StorageRouterList\n            from ovs.extensions.generic.sshclient import SSHClient, UnableToConnectException\n            from ovs.lib.disk import DiskController\n\n            for storagerouter in StorageRouterList.get_storagerouters():\n                try:\n                    client = SSHClient(storagerouter, username='root')\n                except UnableToConnectException:\n                    raise\n\n                # Retrieve all symlinks for all devices\n                # Example of name_alias_mapping:\n                # {'/dev/md0': ['/dev/disk/by-id/md-uuid-ad2de634:26d97253:5eda0a23:96986b76', '/dev/disk/by-id/md-name-OVS-1:0'],\n                #  '/dev/sda': ['/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0'],\n                #  '/dev/sda1': ['/dev/disk/by-uuid/e3e0bc62-4edc-4c6b-a6ce-1f39e8f27e41', '/dev/disk/by-path/pci-0000:03:00.0-sas-0x5000c295fe2ff771-lun-0-part1']}\n                name_alias_mapping = {}\n                alias_name_mapping = {}\n                for path_type in client.dir_list(directory='/dev/disk'):\n                    if path_type in ['by-uuid', 'by-partuuid']:  # UUIDs can change after creating a filesystem on a partition\n                        continue\n                    directory = '/dev/disk/{0}'.format(path_type)\n                    for symlink in client.dir_list(directory=directory):\n                        symlink_path = '{0}/{1}'.format(directory, symlink)\n                        link = client.file_read_link(symlink_path)\n                        if link not in name_alias_mapping:\n                            name_alias_mapping[link] = []\n                        name_alias_mapping[link].append(symlink_path)\n                        alias_name_mapping[symlink_path] = link\n\n                for disk in storagerouter.disks:\n                    if disk.aliases is None:\n                        # noinspection PyProtectedMember\n                        device_path = '/dev/{0}'.format(disk.name)\n                        disk.aliases = name_alias_mapping.get(device_path, [device_path])\n                        disk.save()\n                    for partition in disk.partitions:\n                        # noinspection PyProtectedMember\n                        partition_device = alias_name_mapping.get(partition._data['path'])\n                        if partition.aliases is None:\n                            if partition_device is None:\n                                partition.aliases = []\n                                partition.save()\n                                continue\n                            partition.aliases = name_alias_mapping.get(partition_device, [])\n                            partition.save()\n\n                DiskController.sync_with_reality(storagerouter_guid=storagerouter.guid)\n\n            # Only support ALBA backend type\n            from ovs.dal.lists.backendtypelist import BackendTypeList\n            for backend_type in BackendTypeList.get_backend_types():\n                if backend_type.code != 'alba':\n                    backend_type.delete()\n\n            # Reformat the vpool.metadata information\n            from ovs.dal.lists.vpoollist import VPoolList\n            for vpool in VPoolList.get_vpools():\n                new_metadata = {}\n                for metadata_key, value in vpool.metadata.items():\n                    new_info = {}\n                    storagerouter_guids = [key for key in vpool.metadata.keys() if not key.startswith('backend')]\n                    if isinstance(value, dict):\n                        read_cache = value.get('backend_info', {}).get('fragment_cache_on_read', True)\n                        write_cache = value.get('backend_info', {}).get('fragment_cache_on_write', False)\n                        new_info['backend_info'] = {'alba_backend_guid': value.get('backend_guid'),\n                                                    'backend_guid': None,\n                                                    'frag_size': value.get('backend_info', {}).get('frag_size'),\n                                                    'name': value.get('name'),\n                                                    'policies': value.get('backend_info', {}).get('policies'),\n                                                    'preset': value.get('preset'),\n                                                    'sco_size': value.get('backend_info', {}).get('sco_size'),\n                                                    'total_size': value.get('backend_info', {}).get('total_size')}\n                        new_info['arakoon_config'] = value.get('arakoon_config')\n                        new_info['connection_info'] = {'host': value.get('connection', {}).get('host', ''),\n                                                       'port': value.get('connection', {}).get('port', ''),\n                                                       'local': value.get('connection', {}).get('local', ''),\n                                                       'client_id': value.get('connection', {}).get('client_id', ''),\n                                                       'client_secret': value.get('connection', {}).get('client_secret', '')}\n                        if metadata_key == 'backend':\n                            new_info['caching_info'] = dict((sr_guid, {'fragment_cache_on_read': read_cache, 'fragment_cache_on_write': write_cache}) for sr_guid in storagerouter_guids)\n                    if metadata_key in storagerouter_guids:\n                        metadata_key = 'backend_aa_{0}'.format(metadata_key)\n                    new_metadata[metadata_key] = new_info\n                vpool.metadata = new_metadata\n                vpool.save()\n\n            # Removal of READ role\n            from ovs.dal.lists.diskpartitionlist import DiskPartitionList\n            for partition in DiskPartitionList.get_partitions():\n                if 'READ' in partition.roles:\n                    partition.roles.remove('READ')\n                    partition.save()\n\n        return OVSMigrator.THIS_VERSION\n", "path": "ovs/dal/migration/ovsmigrator.py"}]}