Page MenuHomeVyOS Platform

No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/op-mode-definitions/container.xml.in b/op-mode-definitions/container.xml.in
index ea515fe7c..372786424 100644
--- a/op-mode-definitions/container.xml.in
+++ b/op-mode-definitions/container.xml.in
@@ -1,206 +1,214 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="add">
<children>
<node name="container">
<properties>
<help>Add container image</help>
</properties>
<children>
<tagNode name="image">
<properties>
<help>Pull a new image for container</help>
</properties>
<command>${vyos_op_scripts_dir}/container.py add_image --name "${4}"</command>
</tagNode>
</children>
</node>
</children>
</node>
<node name="connect">
<children>
<tagNode name="container">
<properties>
<help>Attach to a running container</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>podman exec --interactive --tty "$3" /bin/sh</command>
</tagNode>
</children>
</node>
<node name="delete">
<children>
<node name="container">
<properties>
<help>Delete container image</help>
</properties>
<children>
<tagNode name="image">
<properties>
<help>Delete container image</help>
<completionHelp>
<list>all</list>
<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>
</children>
</node>
<node name="generate">
<children>
<node name="container">
<properties>
<help>Generate Container Image</help>
</properties>
<children>
<tagNode name="image">
<properties>
<help>Name of container image (tag)</help>
</properties>
<children>
<tagNode name="path">
<properties>
<help>Path to Dockerfile</help>
<completionHelp>
<list>&lt;filename&gt;</list>
</completionHelp>
</properties>
<command>podman build --net host --layers --force-rm --tag "$4" $6</command>
</tagNode>
</children>
</tagNode>
</children>
</node>
</children>
</node>
<node name="monitor">
<children>
<node name="log">
<children>
<tagNode name="container">
<properties>
<help>Monitor last lines of container log</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/container.py show_log --follow --name "$4"</command>
</tagNode>
</children>
</node>
</children>
</node>
<node name="show">
<children>
<node name="container">
<properties>
<help>Show containers</help>
</properties>
<command>${vyos_op_scripts_dir}/container.py show_container</command>
<children>
<node name="json">
<properties>
<help>Show containers in JSON format</help>
</properties>
<!-- no admin check -->
<command>${vyos_op_scripts_dir}/container.py show_container --raw</command>
</node>
<node name="image">
<properties>
<help>Show container image</help>
</properties>
<command>${vyos_op_scripts_dir}/container.py show_image</command>
<children>
<node name="json">
<properties>
<help>Show container image in JSON format</help>
</properties>
<!-- no admin check -->
<command>${vyos_op_scripts_dir}/container.py show_image --raw</command>
</node>
</children>
</node>
<tagNode name="log">
<properties>
<help>Show logs from a given container</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/container.py show_log --name "$4"</command>
</tagNode>
<node name="network">
<properties>
<help>Show available container networks</help>
</properties>
<!-- no admin check -->
<command>${vyos_op_scripts_dir}/container.py show_network</command>
<children>
<node name="json">
<properties>
<help>Show available container networks in JSON format</help>
</properties>
<!-- no admin check -->
<command>${vyos_op_scripts_dir}/container.py show_network --raw</command>
</node>
</children>
</node>
</children>
</node>
<node name="log">
<children>
<tagNode name="container">
<properties>
<help>Show logs from a given container</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/container.py show_log --name "$4"</command>
</tagNode>
</children>
</node>
</children>
</node>
<node name="restart">
<children>
<tagNode name="container">
<properties>
<help>Restart a given container</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/container.py restart --name="$3"</command>
</tagNode>
</children>
</node>
<node name="update">
<properties>
<help>Update data for a service</help>
</properties>
<children>
<node name="container">
<properties>
<help>Update a container image</help>
</properties>
<children>
<tagNode name="image">
<properties>
<help>Update container image</help>
<completionHelp>
<path>container name</path>
</completionHelp>
</properties>
<command>bash -c 'if cli-shell-api existsActive container name "'$4'"; then podman pull $(cli-shell-api returnActiveValue container name "'$4'" image); else echo "Container '$4' does not exist"; fi'</command>
</tagNode>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/src/op_mode/container.py b/src/op_mode/container.py
index fe81636d2..feb9f41cc 100755
--- a/src/op_mode/container.py
+++ b/src/op_mode/container.py
@@ -1,162 +1,184 @@
#!/usr/bin/env python3
#
# Copyright VyOS maintainers and contributors <maintainers@vyos.io>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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
from vyos.utils.process import cmd
from vyos.utils.process import rc_cmd
import vyos.opmode
def _get_json_data(command: str) -> list:
"""
Get container command format JSON
"""
return cmd(f'{command} --format json')
def _get_raw_data(command: str) -> list:
json_data = _get_json_data(command)
data = json.loads(json_data)
return data
def add_image(name: str):
""" Pull image from container registry. If registry authentication
is defined within VyOS CLI, credentials are used to login befroe pull """
from vyos.configquery import ConfigTreeQuery
conf = ConfigTreeQuery()
container = conf.get_config_dict(['container', 'registry'])
do_logout = False
if 'registry' in container:
for registry, registry_config in container['registry'].items():
if 'disable' in registry_config:
continue
if 'authentication' in registry_config:
do_logout = True
if {'username', 'password'} <= set(registry_config['authentication']):
username = registry_config['authentication']['username']
password = registry_config['authentication']['password']
cmd = f'podman login --username {username} --password {password} {registry}'
rc, out = rc_cmd(cmd)
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':
# gather list of all images and pass them to the removal list
name = cmd('sudo podman image ls --quiet')
# If there are no container images left, we can not delete them all
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'
container_data = _get_raw_data(command)
if raw:
return container_data
else:
return cmd(command)
def show_image(raw: bool):
command = 'podman image ls'
container_data = _get_raw_data('podman image ls')
if raw:
return container_data
else:
return cmd(command)
def show_network(raw: bool):
command = 'podman network ls'
container_data = _get_raw_data(command)
if raw:
return container_data
else:
return cmd(command)
def restart(name: str):
from vyos.utils.process import rc_cmd
rc, output = rc_cmd(f'systemctl restart vyos-container-{name}.service')
if rc != 0:
print(output)
return None
print(f'Container "{name}" restarted!')
return output
def show_log(name: str, follow: bool = False, raw: bool = False):
"""
Show or monitor logs for a specific container.
Use --follow to continuously stream logs.
"""
from vyos.configquery import ConfigTreeQuery
conf = ConfigTreeQuery()
container = conf.get_config_dict(['container', 'name', name], get_first_key=True, with_recursive_defaults=True)
log_type = container.get('log-driver')
if log_type == 'k8s-file':
if follow:
log_command_list = ['sudo', 'podman', 'logs', '--follow', '--names', name]
else:
log_command_list = ['sudo', 'podman', 'logs', '--names', name]
elif log_type == 'journald':
if follow:
log_command_list = ['journalctl', '--follow', '--unit', f'vyos-container-{name}.service']
else:
log_command_list = ['journalctl', '-e', '--no-pager', '--unit', f'vyos-container-{name}.service']
elif log_type == 'none':
print(f'Container "{name}" has disabled logs.')
return None
else:
raise vyos.opmode.InternalError(f'Unknown log type "{log_type}" for container "{name}".')
process = None
try:
process = subprocess.Popen(log_command_list,
stdout=sys.stdout,
stderr=sys.stderr)
process.wait()
except KeyboardInterrupt:
if process:
process.terminate()
process.wait()
return None
except Exception as e:
raise vyos.opmode.InternalError(f"Error starting logging command: {e} ")
return None
if __name__ == '__main__':
try:
res = vyos.opmode.run(sys.modules[__name__])
if res:
print(res)
except (ValueError, vyos.opmode.Error) as e:
print(e)
sys.exit(1)

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 26, 12:09 PM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4285110
Default Alt Text
(14 KB)

Event Timeline