api_test.py revision f10e04e36170dbd0faae3a667d53f0af1ef6a13a
183bea41fa640dc8117f3eb45ff935cd81377a84Timo Sirainen#!/usr/bin/python3
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# api_test.py: Test/demo of the python3-lxc API
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# (C) Copyright Canonical Ltd. 2012
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Authors:
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Stéphane Graber <stgraber@ubuntu.com>
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# This library is free software; you can redistribute it and/or
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# modify it under the terms of the GNU Lesser General Public
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# License as published by the Free Software Foundation; either
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# version 2.1 of the License, or (at your option) any later version.
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# This library is distributed in the hope that it will be useful,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# but WITHOUT ANY WARRANTY; without even the implied warranty of
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Lesser General Public License for more details.
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# You should have received a copy of the GNU Lesser General Public
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# License along with this library; if not, write to the Free Software
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenimport warnings
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenwarnings.filterwarnings("ignore", "The python-lxc API isn't yet stable")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenimport lxc
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenimport uuid
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenimport sys
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenimport time
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Some constants
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo SirainenLXC_TEMPLATE = "ubuntu"
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# Let's pick a random name, avoiding clashes
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo SirainenCONTAINER_NAME = str(uuid.uuid1())
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo SirainenCLONE_NAME = str(uuid.uuid1())
d8702d15ee7721ed1fcfc8f00a589970bd6b3598Timo Sirainen
d8702d15ee7721ed1fcfc8f00a589970bd6b3598Timo Sirainen## Instantiate the container instance
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Getting instance for '%s'" % CONTAINER_NAME)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer = lxc.Container(CONTAINER_NAME)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.config_file_name == "%s/%s/config" %
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (lxc.default_config_path, CONTAINER_NAME))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(not container.defined)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.init_pid == -1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.name == CONTAINER_NAME)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(not container.running)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.state == "STOPPED")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Create a rootfs
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Creating rootfs using '%s'" % LXC_TEMPLATE)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.create(LXC_TEMPLATE)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.defined)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.name == CONTAINER_NAME
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen == container.get_config_item("lxc.utsname"))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.name in lxc.list_containers())
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Test the config
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Testing the configuration")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencapdrop = container.get_config_item("lxc.cap.drop")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.clear_config_item("lxc.cap.drop")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.set_config_item("lxc.cap.drop", capdrop[:-1])
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.append_config_item("lxc.cap.drop", capdrop[-1])
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.save_config()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(isinstance(capdrop, list))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(capdrop == container.get_config_item("lxc.cap.drop"))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Test the networking
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Testing the networking")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert("name" in container.get_keys("lxc.network.0"))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(len(container.network) == 1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.network[0].hwaddr.startswith("00:16:3e"))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Starting the container
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Starting the container")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.start()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.wait("RUNNING", 3)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.init_pid > 1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.running)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.state == "RUNNING")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Checking IP address
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Getting the interface names")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.get_interfaces() == ('lo', 'eth0'))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Checking IP address
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Getting the IP addresses")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencount = 0
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenips = []
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenwhile not ips or count == 10:
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ips = container.get_ips()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen time.sleep(1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen count += 1
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.attach_wait(lxc.attach_run_command, ["ifconfig", "eth0"],
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen namespaces=(lxc.CLONE_NEWNET + lxc.CLONE_NEWUTS))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(len(ips) > 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Testing cgroups a bit
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Testing cgroup API")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenmax_mem = container.get_cgroup_item("memory.max_usage_in_bytes")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencurrent_limit = container.get_cgroup_item("memory.limit_in_bytes")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.set_cgroup_item("memory.limit_in_bytes", max_mem))
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainenassert(container.get_cgroup_item("memory.limit_in_bytes") != current_limit)
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen## Freezing the container
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainenprint("Freezing the container")
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainencontainer.freeze()
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainencontainer.wait("FROZEN", 3)
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen
57593ca3c443884bac880b8deff7c0655ddd9a30Timo Sirainen# A few basic checks of the current state
57593ca3c443884bac880b8deff7c0655ddd9a30Timo Sirainenassert(container.init_pid > 1)
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainenassert(container.running)
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainenassert(container.state == "FROZEN")
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Unfreezing the container
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Unfreezing the container")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.unfreeze()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.wait("RUNNING", 3)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen# A few basic checks of the current state
4a0641e1ff10f0b0299fd36baf38057c54268e48Timo Sirainenassert(container.init_pid > 1)
7c849dbc7be089175c1a83a84ee7249ed695810dTimo Sirainenassert(container.running)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.state == "RUNNING")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenif len(sys.argv) > 1 and sys.argv[1] == "--with-console":
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ## Attaching to tty1
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen print("Attaching to tty1")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen container.console(tty=1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Shutting down the container
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Shutting down the container")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.shutdown(3)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenif container.running:
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen print("Stopping the container")
66c3f635f2f33905af527d49b27f95322aa7dfa7Timo Sirainen container.stop()
66c3f635f2f33905af527d49b27f95322aa7dfa7Timo Sirainen container.wait("STOPPED", 3)
66c3f635f2f33905af527d49b27f95322aa7dfa7Timo Sirainen
66c3f635f2f33905af527d49b27f95322aa7dfa7Timo Sirainen# A few basic checks of the current state
66c3f635f2f33905af527d49b27f95322aa7dfa7Timo Sirainenassert(container.init_pid == -1)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(not container.running)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(container.state == "STOPPED")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Cloning the container
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Cloning the container")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenclone = lxc.Container(CLONE_NAME)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenclone.clone(container)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenclone.start()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenclone.stop()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenclone.destroy()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen## Destroy the container
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenprint("Destroying the container")
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainencontainer.destroy()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenassert(not container.defined)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen