api_test.py revision 9c83a661397456e1455d739bcadfa38f05ce2fe6
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#!/usr/bin/python3
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# api_test.py: Test/demo of the python3-lxc API
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# (C) Copyright Canonical Ltd. 2012
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Authors:
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Stéphane Graber <stgraber@ubuntu.com>
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# This library is free software; you can redistribute it and/or
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# modify it under the terms of the GNU Lesser General Public
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# License as published by the Free Software Foundation; either
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# version 2.1 of the License, or (at your option) any later version.
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# This library is distributed in the hope that it will be useful,
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# but WITHOUT ANY WARRANTY; without even the implied warranty of
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Lesser General Public License for more details.
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# You should have received a copy of the GNU Lesser General Public
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# License along with this library; if not, write to the Free Software
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin#
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinimport warnings
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinwarnings.filterwarnings("ignore", "The python-lxc API isn't yet stable")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinimport lxc
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinimport uuid
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinimport sys
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinimport time
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Some constants
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey ShabalinLXC_TEMPLATE = "ubuntu"
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# Let's pick a random name, avoiding clashes
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey ShabalinCONTAINER_NAME = str(uuid.uuid1())
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey ShabalinCLONE_NAME = str(uuid.uuid1())
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Instantiate the container instance
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Getting instance for '%s'" % CONTAINER_NAME)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer = lxc.Container(CONTAINER_NAME)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.config_file_name == "%s/%s/config" %
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin (lxc.default_config_path, CONTAINER_NAME))
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(not container.defined)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.init_pid == -1)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.name == CONTAINER_NAME)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(not container.running)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.state == "STOPPED")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Create a rootfs
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Creating rootfs using '%s'" % LXC_TEMPLATE)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.create(LXC_TEMPLATE)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.defined)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.name == CONTAINER_NAME
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin == container.get_config_item("lxc.utsname"))
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.name in lxc.list_containers())
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Test the config
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinprint("Testing the configuration")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincapdrop = container.get_config_item("lxc.cap.drop")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.clear_config_item("lxc.cap.drop")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.set_config_item("lxc.cap.drop", capdrop[:-1])
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.append_config_item("lxc.cap.drop", capdrop[-1])
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.save_config()
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin# A few basic checks of the current state
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(isinstance(capdrop, list))
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(capdrop == container.get_config_item("lxc.cap.drop"))
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Test the networking
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinprint("Testing the networking")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin# A few basic checks of the current state
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert("name" in container.get_keys("lxc.network.0"))
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(len(container.network) == 1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.network[0].hwaddr.startswith("00:16:3e"))
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Starting the container
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Starting the container")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.start()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.wait("RUNNING", 3)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.init_pid > 1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.running)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.state == "RUNNING")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Checking IP address
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Getting the IP addresses")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincount = 0
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinips = []
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinwhile not ips or count == 10:
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin ips = container.get_ips()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin time.sleep(1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin count += 1
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.attach("NETWORK|UTSNAME", "/sbin/ifconfig", "eth0")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(len(ips) > 0)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Testing cgroups a bit
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Testing cgroup API")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinmax_mem = container.get_cgroup_item("memory.max_usage_in_bytes")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincurrent_limit = container.get_cgroup_item("memory.limit_in_bytes")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.set_cgroup_item("memory.limit_in_bytes", max_mem))
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinassert(container.get_cgroup_item("memory.limit_in_bytes") != current_limit)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Freezing the container
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinprint("Freezing the container")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.freeze()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.wait("FROZEN", 3)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.init_pid > 1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.running)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.state == "FROZEN")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Unfreezing the container
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinprint("Unfreezing the container")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.unfreeze()
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalincontainer.wait("RUNNING", 3)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.init_pid > 1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.running)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.state == "RUNNING")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinif len(sys.argv) > 1 and sys.argv[1] == "--with-console":
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin ## Attaching to tty1
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin print("Attaching to tty1")
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin container.console(tty=1)
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalin## Shutting down the container
b031f0d2ca1b40eab86286b82d3c5e8b379122e6Alexey Shabalinprint("Shutting down the container")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.shutdown(3)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinif container.running:
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin print("Stopping the container")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin container.stop()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin container.wait("STOPPED", 3)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin# A few basic checks of the current state
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.init_pid == -1)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(not container.running)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(container.state == "STOPPED")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Cloning the container
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Cloning the container")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinclone = lxc.Container(CLONE_NAME)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinclone.clone(container)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinclone.start()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinclone.stop()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinclone.destroy()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin## Destroy the container
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinprint("Destroying the container")
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalincontainer.destroy()
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalinassert(not container.defined)
262f4e48a51a55ad9cee06abbcfe4a6ad6166f49Alexey Shabalin