1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""This module provides some utilities used by LXC and its tools. 6""" 7 8import common 9from autotest_lib.client.bin import utils 10from autotest_lib.client.common_lib import error 11from autotest_lib.client.common_lib.cros.network import interface 12 13 14def path_exists(path): 15 """Check if path exists. 16 17 If the process is not running with root user, os.path.exists may fail to 18 check if a path owned by root user exists. This function uses command 19 `test -e` to check if path exists. 20 21 @param path: Path to check if it exists. 22 23 @return: True if path exists, otherwise False. 24 """ 25 try: 26 utils.run('sudo test -e "%s"' % path) 27 return True 28 except error.CmdError: 29 return False 30 31 32def get_host_ip(): 33 """Get the IP address of the host running containers on lxcbr*. 34 35 This function gets the IP address on network interface lxcbr*. The 36 assumption is that lxc uses the network interface started with "lxcbr". 37 38 @return: IP address of the host running containers. 39 """ 40 # The kernel publishes symlinks to various network devices in /sys. 41 result = utils.run('ls /sys/class/net', ignore_status=True) 42 # filter out empty strings 43 interface_names = [x for x in result.stdout.split() if x] 44 45 lxc_network = None 46 for name in interface_names: 47 if name.startswith('lxcbr'): 48 lxc_network = name 49 break 50 if not lxc_network: 51 raise error.ContainerError('Failed to find network interface used by ' 52 'lxc. All existing interfaces are: %s' % 53 interface_names) 54 netif = interface.Interface(lxc_network) 55 return netif.ipv4_address 56 57def clone(lxc_path, src_name, new_path, dst_name, snapshot): 58 """Clones a container. 59 60 @param lxc_path: The LXC path of the source container. 61 @param src_name: The name of the source container. 62 @param new_path: The LXC path of the destination container. 63 @param dst_name: The name of the destination container. 64 @param snapshot: Whether or not to create a snapshot clone. 65 """ 66 snapshot_arg = '-s' if snapshot else '' 67 # overlayfs is the default clone backend storage. However it is not 68 # supported in Ganeti yet. Use aufs as the alternative. 69 aufs_arg = '-B aufs' if utils.is_vm() and snapshot else '' 70 cmd = (('sudo lxc-clone --lxcpath {lxcpath} --newpath {newpath} ' 71 '--orig {orig} --new {new} {snapshot} {backing}') 72 .format( 73 lxcpath = lxc_path, 74 newpath = new_path, 75 orig = src_name, 76 new = dst_name, 77 snapshot = snapshot_arg, 78 backing = aufs_arg 79 )) 80 utils.run(cmd) 81 82 83def cleanup_host_mount(host_dir): 84 """Unmounts and removes the given host dir. 85 86 @param host_dir: The host dir to unmount and remove. 87 """ 88 try: 89 utils.run('sudo umount "%s"' % host_dir) 90 except error.CmdError: 91 # Ignore errors. Most likely this occurred because the host dir 92 # was already unmounted. 93 pass 94 utils.run('sudo rm -r "%s"' % host_dir) 95