Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short 2015-01-18 20:50:27 -05:00
parent d1bf6e2e81
commit ae0e8eae4d
7 changed files with 97 additions and 61 deletions

View File

@ -15,7 +15,9 @@
import json
import requests
class Client(object):
def __init__(self, host, cert, key):
self.host = host
self.cert = cert
@ -33,7 +35,7 @@ class Client(object):
cert=(self.cert, self.key), verify=False)
def _delete(self, path):
return requests.delete(self._url(path),
return requests.delete(self._url(path),
cert=(self.cert, self.key), verify=False)
def defined(self, name):
@ -63,7 +65,7 @@ class Client(object):
def start(self, name):
container_start = False
if self.defined(name):
params = {'action':'start'}
params = {'action': 'start'}
response = self._put('/1.0/containers/%s/state' % name, params)
if response.status_code == 200:
container_start = True
@ -72,7 +74,7 @@ class Client(object):
def stop(self, name):
container_stop = False
if self.defined(name):
params = {'action':'start'}
params = {'action': 'start'}
response = self._put('/1.0/containers/%s/state' % name, params)
if response.status_code == 200:
container_stop = True

View File

@ -24,14 +24,18 @@ from nova import utils
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class LXDConfigObject(object):
def __init__(self, **kwargs):
super(LXDConfigObject, self).__init__()
def set_config(self):
pass
class LXDConfigTemplate(LXDConfigObject):
def __init__(self, instance, image_meta):
super(LXDConfigTemplate, self).__init__()
self.instance = instance
@ -40,7 +44,7 @@ class LXDConfigTemplate(LXDConfigObject):
def set_config(self):
templates = []
if (self.image_meta and
self.image_meta.get('properties', {}).get('template')):
self.image_meta.get('properties', {}).get('template')):
lxc_template = self.image_meta['properties'].get('template')
else:
lxc_template = CONF.lxd.lxd_default_template
@ -51,16 +55,19 @@ class LXDConfigTemplate(LXDConfigObject):
if lxc_template in templates:
config_file = os.path.join(CONF.lxd.lxd_root_dir,
self.instance, 'config')
self.instance, 'config')
f = open(config_file, 'w')
f.write('lxc.include = %s/%s.common.conf\n' % (CONF.lxd.lxd_config_dir,
lxc_template))
f.write('lxc.include = %s/%s.userns.conf\n' % (CONF.lxd.lxd_config_dir,
lxc_template))
f.write('lxc.include = %s/%s.common.conf\n'
% (CONF.lxd.lxd_config_dir,
lxc_template))
f.write('lxc.include = %s/%s.userns.conf\n'
% (CONF.lxd.lxd_config_dir,
lxc_template))
class LXDConfigSetName(LXDConfigObject):
def __init__(self, container, instance):
super(LXDConfigSetName, self).__init__()
self.container = container
@ -70,7 +77,9 @@ class LXDConfigSetName(LXDConfigObject):
self.container.append_config_item('lxc.utsname',
self.instance)
class LXDConfigSetRoot(LXDConfigObject):
def __init__(self, container, instance):
super(LXDConfigSetRoot, self).__init__()
self.container = container
@ -83,7 +92,9 @@ class LXDConfigSetRoot(LXDConfigObject):
self.container.append_config_item('lxc.rootfs',
self.container_rootfs)
class LXDConfigSetLog(LXDConfigObject):
def __init__(self, container, instance):
super(LXDConfigSetLog, self).__init__()
self.container = container
@ -96,7 +107,9 @@ class LXDConfigSetLog(LXDConfigObject):
self.container.append_config_item('lxc.logfile',
container_logfile)
class LXDConfigConsole(LXDConfigObject):
def __init__(self, container, instance):
super(LXDConfigConsole, self).__init__()
self.container = container
@ -112,6 +125,7 @@ class LXDConfigConsole(LXDConfigObject):
class LXDUserConfig(LXDConfigObject):
def __init__(self, container, idmap):
super(LXDUserConfig, self).__init__()
self.container = container
@ -121,7 +135,9 @@ class LXDUserConfig(LXDConfigObject):
for ent in self.idmap.lxc_conf_lines():
self.container.append_config_item(*ent)
class LXDSetLimits(LXDConfigObject):
def __init__(self, container, instance):
super(LXDSetLimits, self).__init__()
self.container = container
@ -132,4 +148,3 @@ class LXDSetLimits(LXDConfigObject):
self.container.append_config_item(
'lxc.cgroup.memory.limit_in_bytes',
'%sM' % flavor.memory_mb)

View File

@ -43,10 +43,13 @@ LOG = logging.getLogger(__name__)
MAX_CONSOLE_BYTES = 100 * units.Ki
def get_container_dir(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance)
class Container(object):
def __init__(self, client, virtapi, firewall):
self.client = client
self.virtapi = virtapi
@ -83,7 +86,7 @@ class Container(object):
return log_data
def start_container(self, context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info, flavor):
admin_password, network_info, block_device_info, flavor):
LOG.info(_LI('Starting new instance'), instance=instance)
self.container = lxc.Container(instance['uuid'])
@ -105,21 +108,27 @@ class Container(object):
fileutils.ensure_tree(self.base_dir)
def _fetch_image(self, context, instance):
container_image = os.path.join(self.base_dir, '%s.tar.gz' % instance['image_ref'])
container_image = os.path.join(
self.base_dir, '%s.tar.gz' % instance['image_ref'])
if not os.path.exists(container_image):
images.fetch_to_raw(context, instance['image_ref'], container_image,
images.fetch_to_raw(
context, instance['image_ref'], container_image,
instance['user_id'], instance['project_id'])
if not tarfile.is_tarfile(container_image):
raise exception.NovaException(_('Not an valid image'))
if CONF.use_cow_images:
root_dir = os.path.join(get_container_dir(instance['uuid']), 'rootfs')
self.image = image.ContainerCoW(container_image, instance, root_dir, self.base_dir)
root_dir = os.path.join(
get_container_dir(instance['uuid']), 'rootfs')
self.image = image.ContainerCoW(
container_image, instance, root_dir, self.base_dir)
else:
root_dir = fileutils.ensure_tree(os.path.join(get_container_dir(instance['uuid']),
'rootfs'))
self.image = image.ContainerLocal(container_image, instance, root_dir)
root_dir = fileutils.ensure_tree(
os.path.join(get_container_dir(instance['uuid']),
'rootfs'))
self.image = image.ContainerLocal(
container_image, instance, root_dir)
self.image.create_container()
@ -194,6 +203,6 @@ class Container(object):
def _neutron_failed_callback(self, event_name, instance):
LOG.error(_LE('Neutron Reported failure on event '
'%(event)s for instance %(uuid)s'),
{'event': event_name, 'uuid': instance.uuid})
{'event': event_name, 'uuid': instance.uuid})
if CONF.vif_plugging_is_fatal:
raise exception.VirtualInterfaceCreateException()

View File

@ -53,8 +53,8 @@ from . import host_utils
lxd_opts = [
cfg.StrOpt('lxd_client_cert',
default='/etc/lxd/client.crt',
help='LXD client certificate'),
default='/etc/lxd/client.crt',
help='LXD client certificate'),
cfg.StrOpt('lxd_client_key',
default='/etc/lxd/client.key',
help='LXD client key'),
@ -62,18 +62,18 @@ lxd_opts = [
default='127.0.0.1:8443',
help='LXD API Server'),
cfg.StrOpt('lxd_root_dir',
default='/var/lib/lxd/lxc',
help='Default LXD directory'),
default='/var/lib/lxd/lxc',
help='Default LXD directory'),
cfg.StrOpt('lxd_default_template',
default='ubuntu-cloud',
help='Default LXC template'),
default='ubuntu-cloud',
help='Default LXC template'),
cfg.StrOpt('lxd_template_dir',
default='/usr/share/lxc/templates',
help='Default template directory'),
default='/usr/share/lxc/templates',
help='Default template directory'),
cfg.StrOpt('lxd_config_dir',
default='/usr/share/lxc/config',
help='Default lxc config dir')
]
default='/usr/share/lxc/config',
help='Default lxc config dir')
]
CONF = cfg.CONF
@ -82,11 +82,12 @@ CONF.import_opt('host', 'nova.netconf')
LOG = logging.getLogger(__name__)
class LXDDriver(driver.ComputeDriver):
capabilities = {
"has_imagecache": False,
"supports_recreate": False,
}
}
"""LXD hypervisor driver."""
@ -135,26 +136,22 @@ class LXDDriver(driver.ComputeDriver):
def poll_rebooting_instances(self, timeout, instances):
raise NotImplemented()
def migrate_disk_and_power_off(self, context, instance, dest,
flavor, network_info,
block_device_info=None,
timeout=0, retry_interval=0):
raise NotImplemented()
def finish_revert_migration(self, context, instance, network_info,
block_device_info=None, power_on=True):
raise NotImplemented()
def post_live_migration_at_destination(self, context, instance,
network_info,
block_migration=False,
block_device_info=None):
raise NotImplemented()
def power_off(self, instance, shutdown_timeout=0, shutdown_attempts=0):
self.client.stop(instance['uuid'])
@ -210,11 +207,11 @@ class LXDDriver(driver.ComputeDriver):
raise NotImplemented()
def get_info(self, instance):
if self.client.running(instance['uuid']):
if self.client.running(instance['uuid']):
pstate = power_state.RUNNING
else:
else:
pstate = power_state.SHUTDOWN
return hardware.InstanceInfo(state=pstate,
return hardware.InstanceInfo(state=pstate,
max_mem_kb=0,
mem_kb=0,
num_cpu=2,
@ -233,7 +230,7 @@ class LXDDriver(driver.ComputeDriver):
self.firewall_driver.refresh_rules(instance)
def refresh_provider_fw_rules(self):
self.firewall_driver.refresh_provider_fw_rules()
self.firewall_driver.refresh_provider_fw_rules()
def get_available_resource(self, nodename):
"""Updates compute manager resource info on ComputeNode table.
@ -253,7 +250,7 @@ class LXDDriver(driver.ComputeDriver):
data["local_gb"] = disk['total'] / units.Gi
data["vcpus_used"] = 1
data["memory_mb_used"] = memory['used'] / units.Mi
data["local_gb_used"] = disk['used'] / units.Gi
data["local_gb_used"] = disk['used'] / units.Gi
data["hypervisor_type"] = "lxd"
data["hypervisor_version"] = "1.0"
data["hypervisor_hostname"] = nodename
@ -265,7 +262,8 @@ class LXDDriver(driver.ComputeDriver):
def ensure_filtering_rules_for_instance(self, instance_ref, network_info):
self.firewall_driver.setup_basic_filtering(instance_ref, network_info)
self.firewall_driver.prepare_instance_filter(instance_ref, network_info)
self.firewall_driver.prepare_instance_filter(
instance_ref, network_info)
def unfilter_instance(self, instance, network_info):
self.firewall_driver.unfilter_instance(instance, network_info)
@ -273,5 +271,3 @@ class LXDDriver(driver.ComputeDriver):
def get_available_nodes(self, refresh=False):
hostname = socket.gethostname()
return [hostname]

View File

@ -14,6 +14,7 @@
import os
def get_fs_info(path):
"""get free/used/total space info for a filesystem
@ -32,6 +33,7 @@ def get_fs_info(path):
'free': free,
'used': used}
def get_memory_mb_usage():
"""Get the used memory size(MB) of the host.
@ -44,7 +46,7 @@ def get_memory_mb_usage():
idx2 = m.index('MemFree:')
idx3 = m.index('Buffers:')
idx4 = m.index('Cached:')
total = int(m[idx1 + 1])
avail = int(m[idx2 + 1]) + int(m[idx3 + 1]) + int(m[idx4 + 1])

View File

@ -22,6 +22,7 @@ from . import utils as container_utils
LOG = logging.getLogger(__name__)
def write_image(idmap, image, root_dir):
tar = ['tar', '--directory', root_dir,
'--anchored', '--numeric-owner', '-xpzf', image]
@ -31,7 +32,9 @@ def write_image(idmap, image, root_dir):
args = tuple(nsexec + tar)
utils.execute(*args, check_exit_code=[0, 2])
class ContainerImage(object):
def __init__(self, **kwargs):
super(ContainerImage, self).__init__()
@ -41,7 +44,9 @@ class ContainerImage(object):
def remove_contianer(self):
pass
class ContainerLocal(ContainerImage):
def __init__(self, image, instance, root_dir):
super(ContainerLocal, self).__init__()
self.image = image
@ -53,13 +58,15 @@ class ContainerLocal(ContainerImage):
def create_container(self):
(user, group) = self.idmap.get_user()
utils.execute('chown', '%s:%s' % (user, group), self.root_dir,
run_as_root=True)
run_as_root=True)
write_image(self.idmap, self.image, self.root_dir)
def remove_container(self):
pass
class ContainerCoW(ContainerImage):
def __init__(self, image, instance, root_dir, base_dir):
super(ContainerCoW, self).__init__()
self.idmap = container_utils.LXCUserIdMap()

View File

@ -48,9 +48,10 @@ def write_lxc_config(instance, vif):
bridge = vif['network']['bridge']
f.write('lxc.network.link = %s\n' % bridge)
class LXDGenericDriver(object):
def _get_vif_driver(self, vif):
vif_type = vif['type']
if vif_type is None:
@ -70,7 +71,9 @@ class LXDGenericDriver(object):
vif_driver = self._get_vif_driver(vif)
vif_driver.unplug(instance, vif)
class LXDOpenVswitchDriver(object):
def plug(self, instance, vif):
iface_id = self._get_ovs_interfaceid(vif)
br_name = self._get_br_name(vif['id'])
@ -81,11 +84,11 @@ class LXDOpenVswitchDriver(object):
utils.execute('brctl', 'setfd', br_name, 0, run_as_root=True)
utils.execute('brctl', 'stp', br_name, 'off', run_as_root=True)
utils.execute('tee',
('/sys/class/net/%s/bridge/multicast_snooping' %
br_name),
process_input='0',
run_as_root=True,
check_exit_code=[0, 1])
('/sys/class/net/%s/bridge/multicast_snooping' %
br_name),
process_input='0',
run_as_root=True,
check_exit_code=[0, 1])
if not linux_net.device_exists(v2_name):
linux_net._create_veth_pair(v1_name, v2_name)
@ -115,7 +118,7 @@ class LXDOpenVswitchDriver(object):
v2_name)
except processutils.ProcessExecutionError:
LOG.exception(_("Failed while unplugging vif"),
instance=instance)
instance=instance)
def _get_bridge_name(self, vif):
return vif['network']['bridge']
@ -130,22 +133,24 @@ class LXDOpenVswitchDriver(object):
return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN],
("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN])
class LXDNetworkBridgeDriver(object):
def plug(self, container, instance, vif):
network = vif['network']
if (not network.get_meta('multi_host', False) and
network.get_meta('should_create_bridge', False)):
if network.get_meta('should_create_vlan', False):
iface = CONF.vlan_interface or \
network.get_meta('bridge_interface')
LOG.debug('Ensuring vlan %(vlan)s and bridge %(bridge)s',
{'vlan': network.get_meta('vlan'),
'bridge': vif['network']['bridge']},
instance=instance)
linux_net.LinuxBridgeInterfaceDriver.ensure_vlan_bridge(
iface = CONF.vlan_interface or \
network.get_meta('bridge_interface')
LOG.debug('Ensuring vlan %(vlan)s and bridge %(bridge)s',
{'vlan': network.get_meta('vlan'),
'bridge': vif['network']['bridge']},
instance=instance)
linux_net.LinuxBridgeInterfaceDriver.ensure_vlan_bridge(
network.get_meta('vlan'),
vif['network']['bridge'],
iface)
vif['network']['bridge'],
iface)
else:
iface = CONF.flat_interface or \
network.get_meta('bridge_interface')