Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions libcloud/compute/drivers/ovh.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
NodeImage,
NodeDriver,
NodeLocation,
NodeState,
StorageVolume,
VolumeSnapshot,
)
Expand Down Expand Up @@ -210,7 +211,21 @@ def list_images(self, location=None, ex_size=None):
params["flavorId"] = ex_size.id
response = self.connection.request(action, params=params)

return self._to_images(response.object)
public_images = self._to_images(response.object)

action_snapshot = self._get_project_action("snapshot")
params_snapshot = {}

if location:
params_snapshot["region"] = location.id

# if ex_size:
# params["flavorType"] = ex_size.
Comment on lines +222 to +223
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is commented-out/incomplete code left in this method (# if ex_size: / params["flavorType"] = ex_size.). Since it can't work as-is and doesn't document an implemented behavior, it should be removed or replaced with a proper implementation and explanation.

Suggested change
# if ex_size:
# params["flavorType"] = ex_size.

Copilot uses AI. Check for mistakes.
response_snapshot = self.connection.request(action_snapshot, params=params_snapshot)
private_images = self._to_images(response_snapshot.object)
Comment on lines +216 to +225
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list_images() now makes an additional request to the snapshot endpoint, but the existing OVH compute unit tests/mock transport don't provide a handler/fixture for that URL. This change will make libcloud/test/compute/test_ovh.py::test_list_images fail unless the mock and fixtures are updated (and ideally assertions added for snapshot images).

Suggested change
action_snapshot = self._get_project_action("snapshot")
params_snapshot = {}
if location:
params_snapshot["region"] = location.id
# if ex_size:
# params["flavorType"] = ex_size.
response_snapshot = self.connection.request(action_snapshot, params=params_snapshot)
private_images = self._to_images(response_snapshot.object)
try:
action_snapshot = self._get_project_action("snapshot")
params_snapshot = {}
if location:
params_snapshot["region"] = location.id
# if ex_size:
# params["flavorType"] = ex_size.
response_snapshot = self.connection.request(
action_snapshot, params=params_snapshot
)
private_images = self._to_images(response_snapshot.object)
except Exception:
# If the snapshot endpoint is not available or not mocked,
# gracefully fall back to no private images.
private_images = []

Copilot uses AI. Check for mistakes.

return public_images + private_images


def get_image(self, image_id):
action = self._get_project_action("image/%s" % image_id)
Expand Down Expand Up @@ -557,7 +572,7 @@ def _to_node(self, obj):
return Node(
id=obj["id"],
name=obj["name"],
state=self.NODE_STATE_MAP[obj["status"]],
state=self.NODE_STATE_MAP.get(obj["status"], NodeState.UNKNOWN),
public_ips=public_ips,
private_ips=[],
driver=self,
Expand Down Expand Up @@ -585,7 +600,7 @@ def _to_sizes(self, objs):
return [self._to_size(obj) for obj in objs]

def _to_image(self, obj):
extra = {"region": obj["region"], "visibility": obj["visibility"]}
extra = {"region": obj["region"], "visibility": obj["visibility"], "status": obj["status"]}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_to_image now unconditionally reads obj["status"], but the OVH image list/details responses used elsewhere in the driver (and in existing fixtures) don't include a status field. This will raise a KeyError when calling list_images() / get_image(). Use obj.get("status") (or a sensible default) and keep the extra fields optional.

Suggested change
extra = {"region": obj["region"], "visibility": obj["visibility"], "status": obj["status"]}
extra = {}
for key in ("region", "visibility", "status"):
if key in obj:
extra[key] = obj[key]

Copilot uses AI. Check for mistakes.

return NodeImage(id=obj["id"], name=obj["name"], driver=self, extra=extra)

Expand Down Expand Up @@ -631,3 +646,16 @@ def _to_snapshots(self, objs):

def _ex_connection_class_kwargs(self):
return {"ex_consumer_key": self.consumer_key, "region": self.region}

def create_image(self, node, name, description=None):
action = self._get_project_action("instance/%s/snapshot" % node.id)
response = self.connection.request(action, method="POST", data={"snapshotName": name})
Comment on lines +651 to +652
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace at the end of this line should be removed to keep the file clean and avoid style/lint noise.

Copilot uses AI. Check for mistakes.

return self._to_image({
"id": response.object["snapshotId"],
"name": name,
"region": node.extra.get("region"),
"visibility": "private",
"status": "creating",
})

Loading