genegr commented on code in PR #13061:
URL: https://github.com/apache/cloudstack/pull/13061#discussion_r3718753507


##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/MultipathNVMeOFPool.java:
##########
@@ -0,0 +1,157 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.hypervisor.kvm.storage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.utils.qemu.QemuImg;
+import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
+import org.joda.time.Duration;
+
+import com.cloud.agent.api.to.HostTO;
+import com.cloud.hypervisor.kvm.resource.KVMHABase.HAStoragePool;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.ProvisioningType;
+
+/**
+ * KVMStoragePool for NVMe-over-Fabrics pools. Mirror of
+ * {@link MultipathSCSIPool} for adapters based on
+ * {@link MultipathNVMeOFAdapterBase}. Every data operation is delegated
+ * back to the adapter; the pool itself only tracks addressing/identity.
+ */
+public class MultipathNVMeOFPool implements KVMStoragePool {
+    private final String uuid;
+    private final String sourceHost;
+    private final int sourcePort;
+    private final String sourceDir;
+    private final Storage.StoragePoolType storagePoolType;
+    private final StorageAdaptor storageAdaptor;
+    private final Map<String, String> details;
+    private long capacity;
+    private long used;
+    private long available;
+
+    public MultipathNVMeOFPool(String uuid, String host, int port, String path,
+            Storage.StoragePoolType poolType, Map<String, String> poolDetails, 
StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = host;
+        this.sourcePort = port;
+        this.sourceDir = path;
+        this.storagePoolType = poolType;
+        this.storageAdaptor = adaptor;
+        this.details = poolDetails;
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    public MultipathNVMeOFPool(String uuid, StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = null;
+        this.sourcePort = -1;
+        this.sourceDir = null;
+        this.storagePoolType = Storage.StoragePoolType.NVMeTCP;
+        this.storageAdaptor = adaptor;
+        this.details = new HashMap<>();
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
ProvisioningType provisioningType, long size, byte[] passphrase) {
+        return null;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
PhysicalDiskFormat format, ProvisioningType provisioningType, long size, byte[] 
passphrase) {
+        return null;
+    }
+

Review Comment:
   These placeholders are deliberate and match the in-tree sibling exactly. 
`MultipathNVMeOFPool` is modelled on `MultipathSCSIPool` (the FC/iSCSI pool 
that has shipped for several releases), and every method flagged here has a 
byte-identical body there:
   
   | Method | `MultipathNVMeOFPool` | `MultipathSCSIPool` |
   |---|---|---|
   | `createPhysicalDisk` (both overloads) | `return null` | `return null` |
   | `deletePhysicalDisk` | `return true` | `return true` |
   | `listPhysicalDisks` | `return null` | `return null` |
   | `refresh()` | `return false` | `return false` |
   | `isExternalSnapshot()` | `return true` | `return true` |
   | `getLocalPath()` | `return null` | `return null` |
   | `createFolder()` | `return false` | `return false` |
   
   On the specific concern that `refresh()` returning `false` is "incorrect 
behavior even when the pool is usable" — `MultipathSCSIPool.refresh()` also 
returns `false`, so if that were harmful it would already be affecting every 
Fibre Channel deployment. The methods that actually matter for this pool type 
(`connectPhysicalDisk`, `disconnectPhysicalDisk`, `getPhysicalDisk`) all 
delegate to the adaptor and are exercised end-to-end.
   
   The reason these are no-ops rather than unimplemented is that this is a 
*dummy* pool object: the adapter dispatches per volume, and an NVMe-TCP 
namespace is not a host-local artifact the way a qcow2 file or an LV is. There 
is no pool-level disk to create, list, or delete on the host.
   
   I'd rather not switch only this class to 
`CloudRuntimeException`/`UnsupportedOperationException`, because it would (a) 
diverge from the sibling that this class is intentionally symmetric with, and 
(b) convert currently-harmless no-ops into hard failures on paths I cannot 
exercise — note that all three in-tree callers of `deletePhysicalDisk` ignore 
the return value and catch only `CloudRuntimeException`, so throwing genuinely 
changes behaviour on volume-delete and backup-delete.
   
   @DaanHoogland this is the one item from the Copilot rounds I have pushed 
back on rather than applied — flagging it explicitly since you asked me to 
resolve or apply. If the project would prefer the stricter contract I'm happy 
to do it, but I think it should land as a separate change covering 
`MultipathSCSIPool` and `MultipathNVMeOFPool` together rather than making the 
two inconsistent here.
   



##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/MultipathNVMeOFPool.java:
##########
@@ -0,0 +1,157 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.hypervisor.kvm.storage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.utils.qemu.QemuImg;
+import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
+import org.joda.time.Duration;
+
+import com.cloud.agent.api.to.HostTO;
+import com.cloud.hypervisor.kvm.resource.KVMHABase.HAStoragePool;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.ProvisioningType;
+
+/**
+ * KVMStoragePool for NVMe-over-Fabrics pools. Mirror of
+ * {@link MultipathSCSIPool} for adapters based on
+ * {@link MultipathNVMeOFAdapterBase}. Every data operation is delegated
+ * back to the adapter; the pool itself only tracks addressing/identity.
+ */
+public class MultipathNVMeOFPool implements KVMStoragePool {
+    private final String uuid;
+    private final String sourceHost;
+    private final int sourcePort;
+    private final String sourceDir;
+    private final Storage.StoragePoolType storagePoolType;
+    private final StorageAdaptor storageAdaptor;
+    private final Map<String, String> details;
+    private long capacity;
+    private long used;
+    private long available;
+
+    public MultipathNVMeOFPool(String uuid, String host, int port, String path,
+            Storage.StoragePoolType poolType, Map<String, String> poolDetails, 
StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = host;
+        this.sourcePort = port;
+        this.sourceDir = path;
+        this.storagePoolType = poolType;
+        this.storageAdaptor = adaptor;
+        this.details = poolDetails;
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    public MultipathNVMeOFPool(String uuid, StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = null;
+        this.sourcePort = -1;
+        this.sourceDir = null;
+        this.storagePoolType = Storage.StoragePoolType.NVMeTCP;
+        this.storageAdaptor = adaptor;
+        this.details = new HashMap<>();
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
ProvisioningType provisioningType, long size, byte[] passphrase) {
+        return null;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
PhysicalDiskFormat format, ProvisioningType provisioningType, long size, byte[] 
passphrase) {
+        return null;
+    }
+
+    @Override
+    public boolean connectPhysicalDisk(String volumeUuid, Map<String, String> 
details) {
+        return storageAdaptor.connectPhysicalDisk(volumeUuid, this, details, 
false);
+    }
+
+    @Override
+    public KVMPhysicalDisk getPhysicalDisk(String volumeId) {
+        return storageAdaptor.getPhysicalDisk(volumeId, this);
+    }
+
+    @Override
+    public boolean disconnectPhysicalDisk(String volumeUuid) {
+        return storageAdaptor.disconnectPhysicalDisk(volumeUuid, this);
+    }
+
+    @Override
+    public boolean deletePhysicalDisk(String volumeUuid, Storage.ImageFormat 
format) {
+        return true;
+    }
+
+    @Override
+    public List<KVMPhysicalDisk> listPhysicalDisks() {
+        return null;
+    }

Review Comment:
   Same finding as the thread above — see [my reply 
there](https://github.com/apache/cloudstack/pull/13061#discussion_r3715037519) 
for the method-by-method comparison with `MultipathSCSIPool` and the rationale.
   



##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/MultipathNVMeOFPool.java:
##########
@@ -0,0 +1,157 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package com.cloud.hypervisor.kvm.storage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.utils.qemu.QemuImg;
+import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
+import org.joda.time.Duration;
+
+import com.cloud.agent.api.to.HostTO;
+import com.cloud.hypervisor.kvm.resource.KVMHABase.HAStoragePool;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.ProvisioningType;
+
+/**
+ * KVMStoragePool for NVMe-over-Fabrics pools. Mirror of
+ * {@link MultipathSCSIPool} for adapters based on
+ * {@link MultipathNVMeOFAdapterBase}. Every data operation is delegated
+ * back to the adapter; the pool itself only tracks addressing/identity.
+ */
+public class MultipathNVMeOFPool implements KVMStoragePool {
+    private final String uuid;
+    private final String sourceHost;
+    private final int sourcePort;
+    private final String sourceDir;
+    private final Storage.StoragePoolType storagePoolType;
+    private final StorageAdaptor storageAdaptor;
+    private final Map<String, String> details;
+    private long capacity;
+    private long used;
+    private long available;
+
+    public MultipathNVMeOFPool(String uuid, String host, int port, String path,
+            Storage.StoragePoolType poolType, Map<String, String> poolDetails, 
StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = host;
+        this.sourcePort = port;
+        this.sourceDir = path;
+        this.storagePoolType = poolType;
+        this.storageAdaptor = adaptor;
+        this.details = poolDetails;
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    public MultipathNVMeOFPool(String uuid, StorageAdaptor adaptor) {
+        this.uuid = uuid;
+        this.sourceHost = null;
+        this.sourcePort = -1;
+        this.sourceDir = null;
+        this.storagePoolType = Storage.StoragePoolType.NVMeTCP;
+        this.storageAdaptor = adaptor;
+        this.details = new HashMap<>();
+        this.capacity = 0;
+        this.used = 0;
+        this.available = 0;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
ProvisioningType provisioningType, long size, byte[] passphrase) {
+        return null;
+    }
+
+    @Override
+    public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, 
PhysicalDiskFormat format, ProvisioningType provisioningType, long size, byte[] 
passphrase) {
+        return null;
+    }
+
+    @Override
+    public boolean connectPhysicalDisk(String volumeUuid, Map<String, String> 
details) {
+        return storageAdaptor.connectPhysicalDisk(volumeUuid, this, details, 
false);
+    }
+
+    @Override
+    public KVMPhysicalDisk getPhysicalDisk(String volumeId) {
+        return storageAdaptor.getPhysicalDisk(volumeId, this);
+    }
+
+    @Override
+    public boolean disconnectPhysicalDisk(String volumeUuid) {
+        return storageAdaptor.disconnectPhysicalDisk(volumeUuid, this);
+    }
+
+    @Override
+    public boolean deletePhysicalDisk(String volumeUuid, Storage.ImageFormat 
format) {
+        return true;
+    }
+
+    @Override
+    public List<KVMPhysicalDisk> listPhysicalDisks() {
+        return null;
+    }
+
+    @Override
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setCapacity(long capacity) { this.capacity = capacity; }
+    @Override public long getCapacity() { return this.capacity; }
+    public void setUsed(long used) { this.used = used; }
+    @Override public long getUsed() { return this.used; }
+    public void setAvailable(long available) { this.available = available; }
+    @Override public long getAvailable() { return this.available; }
+
+    @Override public boolean refresh() { return false; }

Review Comment:
   Same finding as the thread above — see [my reply 
there](https://github.com/apache/cloudstack/pull/13061#discussion_r3715037519) 
for the method-by-method comparison with `MultipathSCSIPool` and the rationale.
   



-- 
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