Browse Source

Made R/O flag clearing and Importing on all 'Foreign' disks take place sequentially.

Nashwan Azhari 9 years ago
parent
commit
3db95ac42e
1 changed files with 39 additions and 13 deletions
  1. 39 13
      coriolis/osmorphing/osmount/windows.py

+ 39 - 13
coriolis/osmorphing/osmount/windows.py

@@ -59,8 +59,12 @@ class WindowsMountTools(base.BaseOSMountTools):
         """ Writes the given script data to a file and runs diskpart.exe,
         returning the output. """
         tempdir = self._conn.exec_ps_command("$env:TEMP")
+
+        # NOTE: diskpart is interactive, so we must either pipe it its input
+        # or write a couple of one-line files and use `diskpart /s`
         filepath = r"%s\%s.txt" % (tempdir, uuid.uuid4())
         self._conn.write_file(filepath, bytes(script, 'utf-8'))
+
         return self._conn.exec_ps_command("diskpart.exe /s '%s'" % filepath)
 
     def _service_disks_with_status(
@@ -68,17 +72,39 @@ class WindowsMountTools(base.BaseOSMountTools):
             logmsg_fmt="Operating on disk with index '%s'"):
         """ Uses diskpart.exe to detect all disks with the given 'status', and
         execute the given service script after formatting the disk ID in. """
-        # NOTE: diskpart is interactive, so we must either pipe it its input
-        # or write a couple of one-line files and use `diskpart /s`
-        disk_list = self._run_diskpart_script("LIST DISK\r\nEXIT")
-
-        disk_entry_re = r"\s+Disk ([0-9]+)\s+%s\s+" % status
-        for line in disk_list.split("\r\n"):
-            match = re.match(disk_entry_re, line)
-            if match:
-                index = match.group(1)
-                LOG.info(logmsg_fmt, index)
-                self._run_diskpart_script(service_script_with_id_fmt % index)
+        disk_list_script = "LIST DISK\r\nEXIT"
+
+        disk_entry_re = r"\s+Disk (%s)\s+%s\s+"
+        search_disk_entry_re = disk_entry_re % ("[0-9]+", status)
+        # NOTE: some disk operations performed on one disk may have an effect
+        # on others (ex: importing a Dynamic Disk which is part of a Dynamic
+        # Disk Group also imports the other ones), so we must take care to
+        # re-status before performing any operation on any disk => O(n**2)
+        disk_list = self._run_diskpart_script(disk_list_script)
+        servicable_disk_ids = [m.group(1) for m in [
+            re.match(search_disk_entry_re, l) for l in disk_list.split("\r\n")]
+            if m is not None]
+        for disk_id in servicable_disk_ids:
+            curr_disk_entry_re = disk_entry_re % (disk_id, status)
+
+            disk_list = self._run_diskpart_script("LIST DISK\r\nEXIT")
+            for line in disk_list.split("\r\n"):
+                if re.match(curr_disk_entry_re, line):
+                    LOG.info(logmsg_fmt, disk_id)
+                    self._run_diskpart_script(
+                        service_script_with_id_fmt % disk_id)
+                    break
+
+    def _set_foreign_disks_rw_mode(self):
+        # NOTE: in case a Dynamic Disk (which will show up as 'Foreign' to
+        # the worker) is part of a Dynamic Disk group, ALL disks from that
+        # group must be R/W in order to import it (importing one will
+        # trigger the importing of all of them)
+        set_rw_foreign_disk_script_fmt = (
+            "SELECT DISK %s\r\nATTRIBUTES DISK CLEAR READONLY\r\nEXIT")
+        self._service_disks_with_status(
+            "Foreign", set_rw_foreign_disk_script_fmt,
+            logmsg_fmt="Clearing R/O flag on foreign disk with ID '%s'.")
 
     def _import_foreign_disks(self):
         """ Uses diskpart.exe to import all disks which are foreign to the
@@ -87,8 +113,7 @@ class WindowsMountTools(base.BaseOSMountTools):
         # disk cmdlets use, thus any disk which is foreign is is likely
         # still RO, which is why we must change the RO attribute as well:
         import_disk_script_fmt = (
-            "SELECT DISK %s\r\nATTRIBUTES DISK CLEAR READONLY\r\n"
-            "IMPORT\r\nEXIT")
+            "SELECT DISK %s\r\nIMPORT\r\nEXIT")
         self._service_disks_with_status(
             "Foreign", import_disk_script_fmt,
             logmsg_fmt="Importing foreign disk with ID '%s'.")
@@ -127,6 +152,7 @@ class WindowsMountTools(base.BaseOSMountTools):
         self._refresh_storage()
         self._bring_all_disks_online()
         self._set_basic_disks_rw_mode()
+        self._set_foreign_disks_rw_mode()
         self._import_foreign_disks()
         self._refresh_storage()
         fs_roots = self._get_fs_roots()