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]