summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@vyos.io>2025-07-31 15:58:27 +0100
committerGitHub <noreply@github.com>2025-07-31 15:58:27 +0100
commitebd16523072e39848d32e88b13c9b8ff72e86aad (patch)
treefd43ae0f8ce21e6e4bc25cec88a2ba55830c0233
parentc76f1460e3b27849993543612ab870afa2ebe793 (diff)
parenta99ca6d11b52738f2ce6b49f7417a45cf0f4496f (diff)
downloadvyos-1x-ebd16523072e39848d32e88b13c9b8ff72e86aad.tar.gz
vyos-1x-ebd16523072e39848d32e88b13c9b8ff72e86aad.zip
Merge pull request #4590 from c-po/container-image-remove
op-mode: T7403: add an option to forcefully remove a container image
-rw-r--r--op-mode-definitions/container.xml.in10
-rwxr-xr-xsrc/op_mode/container.py31
2 files changed, 36 insertions, 5 deletions
diff --git a/op-mode-definitions/container.xml.in b/op-mode-definitions/container.xml.in
index a284bc970..372786424 100644
--- a/op-mode-definitions/container.xml.in
+++ b/op-mode-definitions/container.xml.in
@@ -42,10 +42,18 @@
<help>Delete container image</help>
<completionHelp>
<list>all</list>
- <script>podman image ls -q</script>
+ <script>sudo bash -c 'podman image ls -q'</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/container.py delete_image --name "${4}"</command>
+ <children>
+ <leafNode name="force">
+ <properties>
+ <help>Force removal of container image</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/container.py delete_image --name "${4}" --force</command>
+ </leafNode>
+ </children>
</tagNode>
</children>
</node>
diff --git a/src/op_mode/container.py b/src/op_mode/container.py
index 089d02dd2..feb9f41cc 100755
--- a/src/op_mode/container.py
+++ b/src/op_mode/container.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import typing
import json
import sys
import subprocess
@@ -56,13 +57,14 @@ def add_image(name: str):
if rc != 0: raise vyos.opmode.InternalError(out)
rc, output = rc_cmd(f'podman image pull {name}')
+ print(output)
if rc != 0:
raise vyos.opmode.InternalError(output)
if do_logout:
rc_cmd('podman logout --all')
-def delete_image(name: str):
+def delete_image(name: str, force: typing.Optional[bool] = False):
from vyos.utils.process import rc_cmd
if name == 'all':
@@ -72,9 +74,30 @@ def delete_image(name: str):
if not name: return
# replace newline with whitespace
name = name.replace('\n', ' ')
- rc, output = rc_cmd(f'podman image rm {name}')
- if rc != 0:
- raise vyos.opmode.InternalError(output)
+ # convert to list
+ name = name.split()
+
+ for image in name:
+ # convert the truncated image ID to a full image ID
+ rc, ancestor = rc_cmd(f'podman inspect {image} --format "{{{{.Id}}}}"')
+ if rc != 0:
+ raise vyos.opmode.InternalError(ancestor)
+ # check if the image ID is an ancestor of any running container
+ rc, in_use = rc_cmd(f'podman ps --filter ancestor={ancestor} -q')
+ if rc != 0:
+ raise vyos.opmode.InternalError(in_use)
+
+ if bool(in_use):
+ error = f'Cannot delete image "{image}" because it is currently '\
+ f'being used by container "{in_use}"!'
+ raise vyos.opmode.InternalError(error)
+
+ tmp = f'podman image rm {image}'
+ if force: tmp += ' --force'
+
+ rc, output = rc_cmd(tmp)
+ if rc != 0:
+ raise vyos.opmode.InternalError(output)
def show_container(raw: bool):
command = 'podman ps --all'