1
0
mirror of https://github.com/projectatomic/atomic.git synced 2026-02-05 18:45:01 +01:00

Move the Atomic class into python library directory.

I am beginning to work on dbus bindings, this will allow the atomic cli and
the atomic_dbus_server app to share the same code.

Renamed atomicpulp to Atomic in the python library.
This commit is contained in:
Dan Walsh
2015-05-14 10:45:35 -04:00
parent 9edbcde168
commit 536349ae04
7 changed files with 558 additions and 540 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.pyc

View File

@@ -1,6 +1,7 @@
import sys, os
from .pulp import PulpServer
from .config import PulpConfig
from .atomic import Atomic
def writeOut(output, lf="\n"):
sys.stdout.flush()
@@ -33,7 +34,7 @@ def push_image_to_pulp(image, server_url, username, password, verify_ssl, docker
pulp.create_repo(image, repo)
except Exception as e:
raise IOError('Failed to create Pulp repository: {0}'.format(e))
try:
writeOut('Uploading image "{0}" to pulp server "{1}"'.format(image, server_url))
pulp.upload_docker_image(image, repo)

550
Atomic/atomic.py Normal file
View File

@@ -0,0 +1,550 @@
import sys, os
import argparse
import gettext
import docker
import json
import subprocess
import getpass
import requests
try:
from subprocess import DEVNULL # pylint: disable=no-name-in-module
except ImportError:
import os
DEVNULL = open(os.devnull, 'wb')
images=[]
def findRepoTag(d, id):
global images
if len(images) == 0:
images = d.images()
for image in images:
if id == image["Id"]:
return image["RepoTags"][0]
return ""
class Atomic(object):
INSTALL_ARGS = ["/usr/bin/docker", "run",
"-t",
"-i",
"--rm",
"--privileged",
"-v", "/:/host",
"--net=host",
"--ipc=host",
"--pid=host",
"-e", "HOST=/host",
"-e", "NAME=NAME",
"-e", "IMAGE=IMAGE",
"-v", "${CONFDIR}:/etc/NAME",
"-v", "${LOGDIR}:/var/log/NAME",
"-v", "${DATADIR}:/var/lib/NAME",
"-e", "CONFDIR=${CONFDIR}",
"-e", "LOGDIR=${LOGDIR}",
"-e", "DATADIR=${DATADIR}",
"--name", "NAME",
"IMAGE"]
SPC_ARGS = ["/usr/bin/docker", "run",
"-t",
"-i",
"--rm",
"--privileged",
"-v", "/:/host",
"-v", "/run:/run",
"-v", "/etc/localtime:/etc/localtime",
"--net=host",
"--ipc=host",
"--pid=host",
"-e", "HOST=/host",
"-e", "NAME=NAME",
"-e", "IMAGE=IMAGE",
"IMAGE" ]
RUN_ARGS = ["/usr/bin/docker", "create",
"-t",
"-i",
"--name", "NAME",
"IMAGE" ]
def __init__(self):
self.d = docker.Client()
self.name = None
self.image = None
self.spc = False
self.inspect = None
self.force = False
self.images = []
def writeOut(self, output, lf="\n"):
sys.stdout.flush()
sys.stdout.write(output + lf)
def get_label(self, label, image=None):
inspect = self._inspect_image(image)
cfg = inspect.get("Config", None)
if cfg:
labels = cfg.get("Labels", [])
if labels and label in labels:
return labels[label]
return ""
def force_delete_containers(self):
if self._inspect_image():
image = self.image
if self.image.find(":") == -1:
image += ":latest"
for c in self.d.containers(all=True):
if c["Image"] == image:
self.d.remove_container(c["Id"], force=True)
def update(self):
if self.force:
self.force_delete_containers()
return subprocess.check_call(["/usr/bin/docker", "pull", self.image])
def pull(self):
prevstatus = ""
prev = ""
for line in self.d.pull(self.image, stream=True):
bar = json.loads(line)
status = bar['status']
if prevstatus != status:
self.writeOut(status, "")
if 'id' not in bar:
continue
if status == "Downloading":
self.writeOut(bar['progress'] + " ")
elif status == "Extracting":
self.writeOut("Extracting: " + bar['id'])
elif status == "Pull complete":
pass
elif status.startswith("Pulling"):
self.writeOut("Pulling: " + bar['id'])
prevstatus = status
self.writeOut("")
def upload(self):
prevstatus = ""
if not self.args.username:
self.args.username = raw_input("Registry Username: ")
if not self.args.password:
self.args.password = getpass.getpass("Registry Password: ")
if self.args.pulp:
return push_image_to_pulp(self.image, self.args.url, self.args.username, self.args.password, self.args.verify_ssl, self.d)
else:
self.d.login(self.args.username, self.args.password)
for line in self.d.push(self.image, stream=True):
bar = json.loads(line)
status = bar['status']
if prevstatus != status:
self.writeOut(status, "")
if 'id' not in bar:
continue
if status == "Uploading":
self.writeOut(bar['progress'] + " ")
elif status == "Push complete":
pass
elif status.startswith("Pushing"):
self.writeOut("Pushing: " + bar['id'])
prevstatus = status
def set_args(self, args):
self.args=args
try:
self.image = args.image
except:
pass
try:
self.command = args.command
except:
self.command = None
try:
self.spc = args.spc
except:
self.spc = False
try:
self.name = args.name
except:
pass
try:
self.force = args.force
except:
pass
if not self.name and self.image is not None:
self.name = self.image.split("/")[-1].split(":")[0]
if self.spc:
self.name = self.name + "-spc"
def _getconfig(self, key, default=None):
assert self.inspect is not None
cfg = self.inspect.get("Config")
if cfg is None:
return default
val = cfg.get(key, default)
if val is None:
return default
return val
def _get_cmd(self):
return self._getconfig("Cmd", [ "/bin/sh" ])
def _get_labels(self):
return self._getconfig("Labels", [])
def _interactive(self):
return (self._getconfig("AttachStdin", False) and
self._getconfig("AttachStdout", False) and
self._getconfig("AttachStderr", False))
def _running(self):
if self._interactive():
cmd = ["/usr/bin/docker", "exec", "-t", "-i", self.name]
if self.command:
cmd += self.command
else:
cmd += self._get_cmd()
return subprocess.check_call(cmd, stderr=DEVNULL)
else:
if self.command:
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command,
stderr=DEVNULL)
else:
self.writeOut("Container is running")
def _start(self):
if self._interactive():
if self.command:
subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command)
else:
return subprocess.check_call(["/usr/bin/docker", "start", "-i", "-a", self.name], stderr=DEVNULL)
else:
if self.command:
subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command)
else:
return subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
def _inspect_image(self, image=None):
try:
if image:
return self.d.inspect_image(image)
return self.d.inspect_image(self.image)
except docker.errors.APIError:
pass
except requests.exceptions.ConnectionError as e:
raise IOError("Unable to communicate with docker daemon: %s\n" % str(e))
return None
def _inspect_container(self):
try:
return self.d.inspect_container(self.name)
except docker.errors.APIError:
pass
except requests.exceptions.ConnectionError as e:
raise IOError("Unable to communicate with docker daemon: %s\n" % str(e))
return None
def _get_args(self, label):
labels = self._get_labels()
if label in labels:
return labels[label].split()
return None
def _check_latest(self):
inspect = self._inspect_image()
if inspect and inspect["Id"] != self.inspect["Image"]:
response = ""
sys.stdout.write("""The '%(name)s' container is using an older version of the installed
'%(image)s' container image. If you wish to use the newer image,
you must either create a new container with a new name or
uninstall the '%(name)s' container.
# atomic uninstall --name %(name)s %(image)s
and create new container on the '%(image)s' image.
atomic update --force %(image)s
removes all containers based on an image.
""" % { "name" : self.name, "image" : self.image} )
def container_run_command(self):
command = "%s run " % sys.argv[0]
if self.spc:
command += "--SPC "
if self.name != self.image:
command += "--name %s " % self.name
command += self.image
return command
def run(self):
self.inspect = self._inspect_container()
if self.inspect:
self._check_latest()
# Container exists
if self.inspect["State"]["Running"]:
return self._running()
else:
return self._start()
else:
if self.command:
raise ValueError("Container '%s' must be running before executing a command into it.\nExecute the following to create the container:\n%s" % (self.name, self.container_run_command()))
# Container does not exist
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
if self.spc:
if self.command:
args = self.SPC_ARGS + self.command
else:
args = self.SPC_ARGS + self._get_cmd()
cmd = self.gen_cmd(args)
self.writeOut(cmd)
else:
missing_RUN = False
args = self._get_args("RUN")
if not args:
missing_RUN = True
args = self.RUN_ARGS + self._get_cmd()
cmd = self.gen_cmd(args)
self.writeOut(cmd)
if missing_RUN:
subprocess.check_call(cmd, env={
"CONFDIR": "/etc/%s" % self.name,
"LOGDIR": "/var/log/%s" % self.name,
"DATADIR":"/var/lib/%s" % self.name}, shell=True, stderr=DEVNULL, stdout=DEVNULL)
return self._start()
subprocess.check_call(cmd, env={
"CONFDIR": "/etc/%s" % self.name,
"LOGDIR": "/var/log/%s" % self.name,
"DATADIR":"/var/lib/%s" % self.name}, shell=True)
def stop(self):
self.inspect = self._inspect_container()
args = self._get_args("STOP")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
subprocess.check_call(cmd, env={
"CONFDIR": "/etc/%s" % self.name,
"LOGDIR": "/var/log/%s" % self.name,
"DATADIR":"/var/lib/%s" % self.name}, shell=True)
# Container exists
if self.inspect["State"]["Running"]:
self.d.stop(self.name)
def _rpmostree(self, *args):
os.execl("/usr/bin/rpm-ostree", "rpm-ostree", *args)
def host_status(self):
self._rpmostree("status")
def host_upgrade(self):
argv = ["upgrade"]
if self.args.reboot:
argv.append("--reboot")
self._rpmostree(*argv)
def host_rollback(self):
argv = ["rollback"]
if self.args.reboot:
argv.append("--reboot")
self._rpmostree(*argv)
def uninstall(self):
self.inspect = self._inspect_container()
if self.force:
self.force_delete_containers()
if self.name != self.image:
try:
# Attempt to remove container, if it exists just return
self.d.stop(self.name)
self.d.remove_container(self.name)
return
except:
# On exception attempt to remove image
pass
try:
self.d.stop(self.image)
self.d.remove_container(self.image)
except docker.errors.APIError:
pass
self.inspect = self._inspect_image()
args = self._get_args("UNINSTALL")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
subprocess.check_call(cmd, env={
"CONFDIR": "/etc/%s" % self.name,
"LOGDIR": "/var/log/%s" % self.name,
"DATADIR":"/var/lib/%s" % self.name}, shell=True)
subprocess.check_call(["/usr/bin/docker", "rmi", self.image])
def gen_cmd(self,cargs):
args = []
for c in cargs:
if c == "IMAGE":
args.append(self.image)
continue
if c == "IMAGE=IMAGE":
args.append("IMAGE=%s" % self.image)
continue
if c == "NAME=NAME":
args.append("NAME=%s" % self.name)
continue
if c == "NAME":
args.append(self.name)
continue
args.append(c)
return " ".join(args)
def info(self):
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
labels = self._get_labels()
for label in labels:
self.writeOut("%-13s: %s" % (label, labels[label]))
def install(self):
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
args = self._get_args("INSTALL")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
return(subprocess.check_call(cmd, env={
"CONFDIR": "/etc/%s" % self.name,
"LOGDIR": "/var/log/%s" % self.name,
"DATADIR":"/var/lib/%s" % self.name}, shell=True))
def help(self):
if os.path.exists("/usr/bin/rpm-ostree"):
return _('Atomic Management Tool')
else:
return _('Atomic Container Tool')
def print_spc(self):
return " ".join(self.SPC_ARGS)
def print_run(self):
return " ".join(self.RUN_ARGS)
def print_install(self):
return " ".join(self.INSTALL_ARGS) + " /usr/bin/INSTALLCMD"
def print_uninstall(self):
return " ".join(self.INSTALL_ARGS) + " /usr/bin/UNINSTALLCMD"
def _get_layer(self, image):
def get_label(label):
return self.get_label(label, image["Id"])
image = self._inspect_image(image)
if not image:
raise ValueError("Image '%s' does not exist" % self.image)
return({ "Id": image['Id'], "Name": get_label("Name"), "Version" : ("%s:%s:%s" % (get_label("Name"),get_label("Version"),get_label("Release"))).strip(":"), "Tag": findRepoTag(self.d, image['Id']), "Parent": image['Parent']})
def get_layers(self):
layers = []
layer = self._get_layer(self.image)
layers.append(layer)
while layer["Parent"] != "":
layer = self._get_layer(layer["Parent"])
layers.append(layer)
return layers
def _get_image(self, image):
def get_label(label):
return self.get_label(label, image["Id"])
return { "Id": image['Id'], "Name": get_label("Name"), "Version" : ("%s:%s:%s" % (get_label("Name"),get_label("Version"),get_label("Release"))).strip(":"), "Tag": image["RepoTags"][0]}
def get_images(self):
if len(self.images) > 0:
return self.images
images = self.d.images()
for image in images:
self.images.append(self._get_image(image))
return self.images
def verify(self):
def get_label(label):
val = self._get_args(label)
if val:
return val[0]
return ""
self.inspect = self._inspect_image()
current_name = get_label("Name")
version = ""
if current_name:
version = "%s:%s:%s" % (current_name,get_label("Version"),get_label("Release"))
prev = ""
name = None
for layer in self.get_layers():
if name == layer["Name"]:
continue
name = layer["Name"]
if len(name)>0:
for i in self.get_images():
if i["Name"] == name:
if i["Version"] > layer["Version"]:
self.writeOut("Image '%s' contains a layer '%s' that is out of date image version '%s' is available." % (self.image, layer["Version"], i["Version"]))
self.writeOut("You should rebuild the '%s' image useing docker build, it could be vulnerable." % (self.image))
break
def version(self):
def get_label(label):
val = self._get_args(label)
if val:
return val[0]
return ""
try:
self.inspect = self.d.inspect_image(self.image)
except docker.errors.APIError:
self.update()
self.inspect = self.d.inspect_image(self.image)
if self.args.recurse:
for layer in self.get_layers():
self.writeOut("%s %s %s" % (layer["Id"],layer["Version"],layer["Tag"]))
else:
layer = self._get_layer(self.image)
self.writeOut("%s %s %s" % (layer["Id"],layer["Version"],layer["Tag"]))

View File

@@ -46,7 +46,7 @@ class PulpServer(object):
#print('Pulp JSON response:\n{0}'.format(json.dumps(r_json, indent=2)))
if 'error_message' in r_json:
sys.stderror.write('Error messages from Pulp response:\n{0}'.format(r_json['error_message']))
sys.stderr.write('Error messages from Pulp response:\n{0}'.format(r_json['error_message']))
if 'spawned_tasks' in r_json:
for task in r_json['spawned_tasks']:

540
atomic Executable file → Normal file
View File

@@ -25,16 +25,8 @@ import sys, os
import argparse
import gettext
import docker
import json
import subprocess
import atomicpulp
import getpass
try:
from subprocess import DEVNULL # pylint: disable=no-name-in-module
except ImportError:
import os
DEVNULL = open(os.devnull, 'wb')
import requests
import Atomic
PROGNAME="atomic"
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
@@ -51,532 +43,6 @@ except IOError:
import builtins
builtins.__dict__['_'] = str
images=[]
def findRepoTag(d, id):
global images
if len(images) == 0:
images = d.images()
for image in images:
if id == image["Id"]:
return image["RepoTags"][0]
return ""
class Atomic(object):
INSTALL_ARGS = ["/usr/bin/docker", "run",
"-t",
"-i",
"--rm",
"--privileged",
"-v", "/:/host",
"--net=host",
"--ipc=host",
"--pid=host",
"-e", "HOST=/host",
"-e", "NAME=NAME",
"-e", "IMAGE=IMAGE",
"-v", "${CONFDIR}:/etc/NAME",
"-v", "${LOGDIR}:/var/log/NAME",
"-v", "${DATADIR}:/var/lib/NAME",
"-e", "CONFDIR=${CONFDIR}",
"-e", "LOGDIR=${LOGDIR}",
"-e", "DATADIR=${DATADIR}",
"--name", "NAME",
"IMAGE"]
SPC_ARGS = ["/usr/bin/docker", "run",
"-t",
"-i",
"--rm",
"--privileged",
"-v", "/:/host",
"-v", "/run:/run",
"-v", "/etc/localtime:/etc/localtime",
"--net=host",
"--ipc=host",
"--pid=host",
"-e", "HOST=/host",
"-e", "NAME=NAME",
"-e", "IMAGE=IMAGE",
"IMAGE" ]
RUN_ARGS = ["/usr/bin/docker", "create",
"-t",
"-i",
"--name", "NAME",
"IMAGE" ]
def __init__(self):
self.d = docker.Client()
self.name = None
self.image = None
self.spc = False
self.inspect = None
self.force = False
self.images = []
def writeOut(self, output, lf="\n"):
sys.stdout.flush()
sys.stdout.write(output + lf)
def get_label(self, label, image=None):
inspect = self._inspect_image(image)
cfg = inspect.get("Config", None)
if cfg:
labels = cfg.get("Labels", [])
if labels and label in labels:
return labels[label]
return ""
def force_delete_containers(self):
if self._inspect_image():
image = self.image
if self.image.find(":") == -1:
image += ":latest"
for c in self.d.containers(all=True):
if c["Image"] == image:
self.d.remove_container(c["Id"], force=True)
def update(self):
if self.force:
self.force_delete_containers()
return subprocess.check_call(["/usr/bin/docker", "pull", self.image])
def pull(self):
prevstatus = ""
prev = ""
for line in self.d.pull(self.image, stream=True):
bar = json.loads(line)
status = bar['status']
if prevstatus != status:
self.writeOut(status, "")
if 'id' not in bar:
continue
if status == "Downloading":
self.writeOut(bar['progress'] + " ")
elif status == "Extracting":
self.writeOut("Extracting: " + bar['id'])
elif status == "Pull complete":
pass
elif status.startswith("Pulling"):
self.writeOut("Pulling: " + bar['id'])
prevstatus = status
self.writeOut("")
def upload(self):
prevstatus = ""
if not self.args.username:
self.args.username = raw_input("Registry Username: ")
if not self.args.password:
self.args.password = getpass.getpass("Registry Password: ")
if self.args.pulp:
return atomicpulp.push_image_to_pulp(self.image, self.args.url, self.args.username, self.args.password, self.args.verify_ssl, self.d)
else:
self.d.login(self.args.username, self.args.password)
for line in self.d.push(self.image, stream=True):
bar = json.loads(line)
status = bar['status']
if prevstatus != status:
self.writeOut(status, "")
if 'id' not in bar:
continue
if status == "Uploading":
self.writeOut(bar['progress'] + " ")
elif status == "Push complete":
pass
elif status.startswith("Pushing"):
self.writeOut("Pushing: " + bar['id'])
prevstatus = status
def set_args(self, args):
self.args=args
try:
self.image = args.image
except:
pass
try:
self.command = args.command
except:
self.command = None
try:
self.spc = args.spc
except:
self.spc = False
try:
self.name = args.name
except:
pass
try:
self.force = args.force
except:
pass
if not self.name and self.image is not None:
self.name = self.image.split("/")[-1].split(":")[0]
if self.spc:
self.name = self.name + "-spc"
def _getconfig(self, key, default=None):
assert self.inspect is not None
cfg = self.inspect.get("Config")
if cfg is None:
return default
val = cfg.get(key, default)
if val is None:
return default
return val
def _get_cmd(self):
return self._getconfig("Cmd", [ "/bin/sh" ])
def _get_labels(self):
return self._getconfig("Labels", [])
def _interactive(self):
return (self._getconfig("AttachStdin", False) and
self._getconfig("AttachStdout", False) and
self._getconfig("AttachStderr", False))
def _running(self):
if self._interactive():
cmd = ["/usr/bin/docker", "exec", "-t", "-i", self.name]
if self.command:
cmd += self.command
else:
cmd += self._get_cmd()
return subprocess.check_call(cmd, stderr=DEVNULL)
else:
if self.command:
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command, stderr=DEVNULL)
else:
self.writeOut("Container is running")
def _start(self):
if self._interactive():
if self.command:
subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command)
else:
return subprocess.check_call(["/usr/bin/docker", "start", "-i", "-a", self.name], stderr=DEVNULL)
else:
if self.command:
subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
return subprocess.check_call(["/usr/bin/docker", "exec", "-t", "-i", self.name] + self.command)
else:
return subprocess.check_call(["/usr/bin/docker", "start", self.name], stderr=DEVNULL)
def _inspect_image(self, image=None):
try:
if image:
return self.d.inspect_image(image)
return self.d.inspect_image(self.image)
except docker.errors.APIError:
pass
except requests.exceptions.ConnectionError as e:
raise IOError("Unable to communicate with docker daemon: %s\n" % str(e))
return None
def _inspect_container(self):
try:
return self.d.inspect_container(self.name)
except docker.errors.APIError:
pass
except requests.exceptions.ConnectionError as e:
raise IOError("Unable to communicate with docker daemon: %s\n" % str(e))
return None
def _get_args(self, label):
labels = self._get_labels()
if label in labels:
return labels[label].split()
return None
def _check_latest(self):
inspect = self._inspect_image()
if inspect and inspect["Id"] != self.inspect["Image"]:
response = ""
sys.stdout.write("""The '%(name)s' container is using an older version of the installed
'%(image)s' container image. If you wish to use the newer image,
you must either create a new container with a new name or
uninstall the '%(name)s' container.
# atomic uninstall --name %(name)s %(image)s
and create new container on the '%(image)s' image.
atomic update --force %(image)s
removes all containers based on an image.
""" % { "name" : self.name, "image" : self.image} )
def container_run_command(self):
command = "%s run " % sys.argv[0]
if self.spc:
command += "--SPC "
if self.name != self.image:
command += "--name %s " % self.name
command += self.image
return command
def _new_env(self):
env = dict(os.environ)
env["CONFDIR"] = "/etc/%s" % self.name
env["LOGDIR"] = "/var/log/%s" % self.name
env["DATADIR"] = "/var/lib/%s" % self.name
return env
def run(self):
self.inspect = self._inspect_container()
if self.inspect:
self._check_latest()
# Container exists
if self.inspect["State"]["Running"]:
return self._running()
else:
return self._start()
else:
if self.command:
raise ValueError("Container '%s' must be running before executing a command into it.\nExecute the following to create the container:\n%s" % (self.name, self.container_run_command()))
# Container does not exist
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
if self.spc:
if self.command:
args = self.SPC_ARGS + self.command
else:
args = self.SPC_ARGS + self._get_cmd()
cmd = self.gen_cmd(args)
self.writeOut(cmd)
else:
missing_RUN = False
args = self._get_args("RUN")
if not args:
missing_RUN = True
args = self.RUN_ARGS + self._get_cmd()
cmd = self.gen_cmd(args)
self.writeOut(cmd)
if missing_RUN:
subprocess.check_call(cmd, env=self._new_env(), shell=True, stderr=DEVNULL, stdout=DEVNULL)
return self._start()
subprocess.check_call(cmd, env=self._new_env(), shell=True)
def stop(self):
self.inspect = self._inspect_container()
args = self._get_args("STOP")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
subprocess.check_call(cmd, env=self._new_env(), shell=True)
# Container exists
if self.inspect["State"]["Running"]:
self.d.stop(self.name)
def _rpmostree(self, *args):
os.execl("/usr/bin/rpm-ostree", "rpm-ostree", *args)
def host_status(self):
self._rpmostree("status")
def host_upgrade(self):
argv = ["upgrade"]
if self.args.reboot:
argv.append("--reboot")
self._rpmostree(*argv)
def host_rollback(self):
argv = ["rollback"]
if self.args.reboot:
argv.append("--reboot")
self._rpmostree(*argv)
def uninstall(self):
self.inspect = self._inspect_container()
if self.force:
self.force_delete_containers()
if self.name != self.image:
try:
# Attempt to remove container, if it exists just return
self.d.stop(self.name)
self.d.remove_container(self.name)
return
except:
# On exception attempt to remove image
pass
try:
self.d.stop(self.image)
self.d.remove_container(self.image)
except docker.errors.APIError:
pass
self.inspect = self._inspect_image()
args = self._get_args("UNINSTALL")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
subprocess.check_call(cmd, env=self._new_env(), shell=True)
subprocess.check_call(["/usr/bin/docker", "rmi", self.image])
def gen_cmd(self,cargs):
args = []
for c in cargs:
if c == "IMAGE":
args.append(self.image)
continue
if c == "IMAGE=IMAGE":
args.append("IMAGE=%s" % self.image)
continue
if c == "NAME=NAME":
args.append("NAME=%s" % self.name)
continue
if c == "NAME":
args.append(self.name)
continue
args.append(c)
return " ".join(args)
def info(self):
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
labels = self._get_labels()
for label in labels:
self.writeOut("%-13s: %s" % (label, labels[label]))
def install(self):
self.inspect = self._inspect_image()
if not self.inspect:
self.update()
self.inspect = self._inspect_image()
args = self._get_args("INSTALL")
if args:
cmd = self.gen_cmd(args)
self.writeOut(cmd)
return subprocess.check_call(cmd, env=self._new_env(), shell=True)
def help(self):
if os.path.exists("/usr/bin/rpm-ostree"):
return _('Atomic Management Tool')
else:
return _('Atomic Container Tool')
def print_spc(self):
return " ".join(self.SPC_ARGS)
def print_run(self):
return " ".join(self.RUN_ARGS)
def print_install(self):
return " ".join(self.INSTALL_ARGS) + " /usr/bin/INSTALLCMD"
def print_uninstall(self):
return " ".join(self.INSTALL_ARGS) + " /usr/bin/UNINSTALLCMD"
def _get_layer(self, image):
def get_label(label):
return self.get_label(label, image["Id"])
image = self._inspect_image(image)
if not image:
raise ValueError("Image '%s' does not exist" % self.image)
return({ "Id": image['Id'], "Name": get_label("Name"), "Version" : ("%s:%s:%s" % (get_label("Name"),get_label("Version"),get_label("Release"))).strip(":"), "Tag": findRepoTag(self.d, image['Id']), "Parent": image['Parent']})
def get_layers(self):
layers = []
layer = self._get_layer(self.image)
layers.append(layer)
while layer["Parent"] != "":
layer = self._get_layer(layer["Parent"])
layers.append(layer)
return layers
def _get_image(self, image):
def get_label(label):
return self.get_label(label, image["Id"])
return { "Id": image['Id'], "Name": get_label("Name"), "Version" : ("%s:%s:%s" % (get_label("Name"),get_label("Version"),get_label("Release"))).strip(":"), "Tag": image["RepoTags"][0]}
def get_images(self):
if len(self.images) > 0:
return self.images
images = self.d.images()
for image in images:
self.images.append(self._get_image(image))
return self.images
def verify(self):
def get_label(label):
val = self._get_args(label)
if val:
return val[0]
return ""
self.inspect = self._inspect_image()
current_name = get_label("Name")
version = ""
if current_name:
version = "%s:%s:%s" % (current_name,get_label("Version"),get_label("Release"))
prev = ""
name = None
for layer in self.get_layers():
if name == layer["Name"]:
continue
name = layer["Name"]
if len(name)>0:
for i in self.get_images():
if i["Name"] == name:
if i["Version"] > layer["Version"]:
self.writeOut("Image '%s' contains a layer '%s' that is out of date image version '%s' is available." % (self.image, layer["Version"], i["Version"]))
self.writeOut("You should rebuild the '%s' image useing docker build, it could be vulnerable." % (self.image))
break
def version(self):
def get_label(label):
val = self._get_args(label)
if val:
return val[0]
return ""
try:
self.inspect = self.d.inspect_image(self.image)
except docker.errors.APIError:
self.update()
self.inspect = self.d.inspect_image(self.image)
if self.args.recurse:
for layer in self.get_layers():
self.writeOut("%s %s %s" % (layer["Id"],layer["Version"],layer["Tag"]))
else:
layer = self._get_layer(self.image)
self.writeOut("%s %s %s" % (layer["Id"],layer["Version"],layer["Tag"]))
def SetFunc(function):
class customAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
@@ -590,7 +56,7 @@ class HelpByDefaultArgumentParser(argparse.ArgumentParser):
sys.exit(2)
if __name__ == '__main__':
atomic=Atomic()
atomic=Atomic.Atomic()
parser = HelpByDefaultArgumentParser(description=atomic.help())
subparser = parser.add_subparsers(help=_("commands"))
@@ -684,7 +150,7 @@ if __name__ == '__main__':
default=False,
action="store_true",
help=_("upload image using pulp"))
config = atomicpulp.PulpConfig().config()
config = Atomic.PulpConfig().config()
uploadp.add_argument("--verify_ssl",
default=config["verify_ssl"],
action="store_true",

View File

@@ -4,4 +4,4 @@
import os
from distutils.core import setup
setup(name = "atomic", scripts=["atomic"], version="1.0", description="Atomic Management Tool", author="Daniel Walsh", author_email="dwalsh@redhat.com", packages=["atomicpulp"])
setup(name = "atomic", scripts=["atomic"], version="1.0", description="Atomic Management Tool", author="Daniel Walsh", author_email="dwalsh@redhat.com", packages=["Atomic"])