rp- commented on code in PR #14194:
URL: https://github.com/apache/cloudstack/pull/14194#discussion_r4327080211


##########
plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java:
##########
@@ -208,6 +220,164 @@ private void makeResourceAvailable(DevelopersApi api, 
String rscName, boolean di
         ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, 
localNodeName, rma);
         handleLinstorApiAnswers(answers,
             String.format("Linstor: Unable to make resource %s available on 
node: %s", rscName, localNodeName));
+        waitForLocalDevice(api, rscName);
+    }
+
+    /**
+     * Waits until the device of resource {@code rscName} exists on this node. 
Making a resource available
+     * returns before udev has created its /dev/drbd/by-res link, so opening 
the device right away can fail
+     * with "No such file or directory".
+     */
+    private void waitForLocalDevice(DevelopersApi api, String rscName) throws 
ApiException {
+        List<ResourceWithVolumes> resources = 
api.viewResources(Collections.singletonList(localNodeName),
+                Collections.singletonList(rscName), Collections.emptyList(), 
null, null, null);
+        if (resources.isEmpty() || resources.get(0).getVolumes().isEmpty()) {
+            throw new CloudRuntimeException(String.format("Linstor: resource 
%s has no volumes on %s",
+                    rscName, localNodeName));
+        }
+        waitForDevice(LinstorUtil.getDevicePathFromResource(resources.get(0)));
+    }
+
+    void waitForDevice(String device) {
+        long deadline = System.currentTimeMillis() + DEVICE_WAIT_MS;
+        while (!Files.exists(Paths.get(device))) {
+            if (System.currentTimeMillis() > deadline) {
+                throw new CloudRuntimeException(String.format("Linstor: device 
%s did not appear within %d ms",
+                        device, DEVICE_WAIT_MS));
+            }
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                throw new CloudRuntimeException("Linstor: interrupted while 
waiting for device " + device, e);
+            }
+        }
+    }
+
+    /**
+     * Creates the scratch space of a pull-mode backup as one resource with a 
volume per size. The resource
+     * definition is created in the pool's resource group, so the group's 
properties and storage pool selection
+     * apply; spawning it from the group would limit the volumes to the 
group's volume groups.
+     *
+     * Copy-before-write runs inline with the guest's writes, so the scratch 
is placed on a storage pool of this
+     * node if there is one, as a plain STORAGE resource: it only lives for 
one backup and needs no replication.
+     * Otherwise, e.g. on a compute node without storage, it is a single DRBD 
replica on another node that this
+     * node attaches diskless.
+     *
+     * The agent deletes the scratch once the backup has ended. If it never 
gets there, e.g. because the agent
+     * crashed, the resource definition has to be deleted manually; its 
{@value #BACKUP_SCRATCH_VM_PROP}
+     * property names the VM.
+     */
+    public Pair<String, List<String>> createBackupScratch(KVMStoragePool pool, 
String vmName, List<Long> sizes) {

Review Comment:
   Yes, and it does now, so after a node crash and restart, Linstor now deletes 
left over scratch resources on start.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to