Misc fixes

Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short 2015-01-12 11:59:14 -05:00
parent c299f10b7e
commit 4012906bae
8 changed files with 157 additions and 99 deletions

View File

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View File

@ -23,6 +23,10 @@ class Client(object):
return requests.put(self._url(path), data=json.dumps(data),
cert=(self.cert, self.key), verify=False)
def _delete(self, path):
return requests.delete(self._url(path),
cert=(self.cert, self.key), verify=False)
def defined(self, name):
container_exists = False
response = self._get('/1.0/containers/%s/state' % name)
@ -64,6 +68,34 @@ class Client(object):
if response.status_code == 200:
container_stop = True
return container_stop
def pause(self, name):
container_pause = False
if self.defined(name):
params = {'action': 'freeze'}
response = self._put('/1.0/containers/%s/state' % name, params)
if response.status_code == 200:
container_pause = True
return container_pause
def resume(self, name):
container_unpause = False
if self.defined(name):
params = {'action': 'unfreeze'}
response = self._put('/1.0/containers/%s/state' % name, params)
if response.status_code == 200:
container_unpause = True
return container_unpause
def destory(self, name):
container_delete = False
if self.defined(name):
response = self._delete('/1.0/containers/%s' % name)
if response.status_code == 200:
container_delete = True
return container_delete
def list(self):

View File

@ -106,3 +106,16 @@ class LXDUserConfig(LXDConfigObject):
def set_config(self):
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
self.instance = instance
def set_config(self):
flavor = self.instance.get_flavor()
self.container.append_config_item(
'lxc.cgroup.memory.limit_in_bytes',
'%sM' % flavor.memory_mb)

View File

@ -1,17 +1,20 @@
import os
import grp
import pwd
import uuid
import lxc
import tarfile
from oslo.config import cfg
from oslo.utils import importutils
from oslo.utils import importutils, units
from nova.i18n import _, _LW, _LE, _LI
from nova.openstack.common import fileutils
from nova.openstack.common import log as logging
from nova import utils
from nova.virt import images
from nova import objects
from nova import exception
from . import config
@ -22,36 +25,62 @@ CONF.import_opt('vif_plugging_timeout', 'nova.virt.driver')
CONF.import_opt('vif_plugging_is_fatal', 'nova.virt.driver')
LOG = logging.getLogger(__name__)
def get_container_rootfs(instance):
return os.path.join(CONF.lxd_root_dir, instance, 'rootfs')
MAX_CONSOLE_BYTES = 100 * units.Ki
def get_container_dir(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance, 'rootfs')
class Container(object):
def __init__(self, client, virtapi):
def __init__(self, client, virtapi, firewall):
self.client = client
self.virtapi = virtapi
self.firewall_driver = firewall
self.container = lxc.Container(instance['uuid'])
self.container.set_config_path(CONF.lxd.lxd_root_dir)
self.container = None
self.idmap = LXCUserIdMap()
self.vif_driver = vif.LXDGenericDriver()
self.base_dir = os.path.join(CONF.instances_path,
CONF.image_cache_subdirectory_name)
def start_container(self, context, instance, image_meta, network_info, block_device_info, flavor):
def init_container(self):
lxc_cgroup = uuid.uuid4()
utils.execute('cgm', 'create', 'all', lxc_cgroup,
run_as_root=True)
utils.execute('cgm', 'chown', 'all', lxc_cgroup,
pwd.getpwuid(os.getuid()).pw_uid,
pwd.getpwuid(os.getuid()).pw_gid,
run_as_root=True)
utils.execute('cgm', 'movepid', 'all', lxc_cgroup, os.getpid())
def get_console_log(self, instance):
console_log = os.path.join(CONF.lxd.lxd_root_dir,
instance['uuid'],
'console.log')
with open(console_log, 'rb') as fp:
log_data, remaining = utils.last_bytes(fp, MAX_CONSOLE_BYTES)
if remaining > 0:
LOG.info(_LI('Truncated console log returned, '
'%d bytes ignored'),
remaining, instance=instance)
return log_data
def start_container(self, context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info, flavor):
LOG.info(_LI('Starting new instance'), instance=instance)
instance_name = instance['uuid']
try:
''' Create the instance directories '''
self._create_container(instance_name)
self.container = lxc.Container(instance['uuid'])
self.container.set_config_path(CONF.lxd.lxd_root_dir)
''' Fetch the image from glance '''
self._fetch_image(context, instance)
''' Create the instance directories '''
self._create_container(instance_name)
''' Start the contianer '''
self._start_container(instance, network_info, image_meta)
except Exception:
LOG.error(_LE('Failed to spawn instance'), instance=instance)
''' Fetch the image from glance '''
self._fetch_image(context, instance)
''' Start the contianer '''
self._start_container(context, instance, network_info, image_meta)
def _create_container(self, instance):
if not os.path.exists(get_container_dir(instance)):
@ -61,9 +90,9 @@ class Container(object):
def _fetch_image(self, context, instance):
(user, group) = self.idmap.get_user()
image = os.path.join(self.base_dir, '%s.tar.gz' % instnce['image_ref'])
image = os.path.join(self.base_dir, '%s.tar.gz' % instance['image_ref'])
if not os.path.exists(image):
images.fetch_to_raw(context, instance['image_ref'], base,
images.fetch_to_raw(context, instance['image_ref'], image,
instance['user_id'], instance['project_id'])
if not tarfile.is_tarfile(image):
raise exception.NovaException(_('Not an valid image'))
@ -74,7 +103,10 @@ class Container(object):
utils.execute('chown', '-R', '%s:%s' % (user, group),
get_container_dir(instance['uuid']), run_as_root=True)
def _start_container(self, instance, network_info, image_meta):
def _start_container(self, context, instance, network_info, image_meta):
with utils.temporary_mutation(context, read_deleted="yes"):
flavor = objects.Flavor.get_by_id(context,
instance['instance_type_id'])
timeout = CONF.vif_plugging_timeout
# check to see if neutron is ready before
# doing anything else
@ -88,13 +120,14 @@ class Container(object):
with self.virtapi.wait_for_instance_event(
instance, events, deadline=timeout,
error_callback=self._neutron_failed_callback):
self._write_config(instance, network_info, image_meta)
self._write_config(instance, network_info, image_meta, flavor)
self._start_network(instance, network_info)
self._start_firewall(instance, network_info)
self.client.start(instance['uuid'])
except exception.VirtualInterfaceCreateException:
LOG.info(_LW('Failed'))
def _write_config(self, instance, network_info, image_meta):
def _write_config(self, instance, network_info, image_meta, flavor):
template = config.LXDConfigTemplate(instance['uuid'], image_meta)
template.set_config()
@ -115,15 +148,27 @@ class Container(object):
idmap = config.LXDUserConfig(self.container, self.idmap)
idmap.set_config()
limit = config.LXDSetLimits(self.container, instance)
limit.set_config()
self.container.save_config()
def _start_network(self, instance, network_info):
for vif in network_info:
self.vif_driver.plug(instance, vif)
def _teardown_network(self, instance, network_info):
def teardown_network(self, instance, network_info):
for vif in network_info:
self.vif_driver.unplug(instancece, vif)
self._stop_firewall(instance, network_info)
def _start_firewall(self, instance, network_info):
self.firewall_driver.setup_basic_filtering(instance, network_info)
self.firewall_driver.prepare_instance_filter(instance, network_info)
self.firewall_driver.apply_instance_filter(instance, network_info)
def _stop_firewall(self, instnce, network_inf):
self.firewall_driver.unfilter_instance(instance, network_info)
def _get_neutron_events(self, network_info):
return [('network-vif-plugged', vif['id'])

View File

@ -23,6 +23,9 @@ Nova LXD Driver
import socket
import contextlib
import psutil
from oslo.utils import units
from oslo.config import cfg
from oslo.serialization import jsonutils
@ -40,11 +43,13 @@ from nova.openstack.common import log as logging
from nova import utils
from nova.virt import diagnostics
from nova.virt import driver
from nova.virt import firewall
from nova.virt import hardware
from nova.virt import virtapi
from . import client
from . import container
from . import host_utils
lxd_opts = [
cfg.StrOpt('lxd_client_cert',
@ -54,7 +59,7 @@ lxd_opts = [
default='/etc/lxd/client.key',
help='LXD client key'),
cfg.StrOpt('lxd_client_host',
default='10.5.0.10:8443',
default='10.5.0.12:8443',
help='LXD API Server'),
cfg.StrOpt('lxd_root_dir',
default='/var/lib/lxd/lxc',
@ -92,12 +97,15 @@ class LXDDriver(driver.ComputeDriver):
self.client = client.Client(CONF.lxd.lxd_client_host,
CONF.lxd.lxd_client_cert,
CONF.lxd.lxd_client_key)
self.firewall_driver = firewall.load_driver(
default='nova.virt.firewall.NoopFirewallDriver')
self.container = container.Container(self.client,
self.virtapi)
self.virtapi,
self.firewall_driver)
def init_host(self, host):
return
return self.container.init_container()
def list_instances(self):
return self.client.list()
@ -149,7 +157,7 @@ class LXDDriver(driver.ComputeDriver):
self.client.stop(instance['uuid'])
def power_on(self, context, instance, network_info, block_device_info):
self.client.start(instance['uuid])
self.client.start(instance['uuid'])
def soft_delete(self, instance):
pass
@ -158,10 +166,10 @@ class LXDDriver(driver.ComputeDriver):
raise NotImplemented()
def pause(self, instance):
raise NotImplemented()
self.client.pause(instance['uuid'])
def unpause(self, instance):
raise NotImplemented()
self.client.unpause(instance['uuid'])
def suspend(self, instance):
raise NotImplemented()
@ -171,11 +179,12 @@ class LXDDriver(driver.ComputeDriver):
def destroy(self, context, instance, network_info, block_device_info=None,
destroy_disks=True, migrate_data=None):
pass
self.client.destory(instance['uuid'])
self.cleanup(context, instance, network_info, block_device_info)
def cleanup(self, context, instance, network_info, block_device_info=None,
destroy_disks=True, migrate_data=None, destroy_vifs=True):
pass
self.container.teardown_network(instance, network_info)
def attach_volume(self, context, connection_info, instance, mountpoint,
disk_bus=None, device_type=None, encryption=None):
@ -210,33 +219,19 @@ class LXDDriver(driver.ComputeDriver):
cpu_time_ns=0)
def get_console_output(self, context, instance):
return 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE'
def get_vnc_console(self, context, instance):
return True
def get_spice_console(self, context, instance):
return True
def get_rdp_console(self, context, instance):
return True
def get_serial_console(self, context, instance):
return True
def get_console_pool_info(self, console_type):
return True
return self.container.get_console_log(instance)
def refresh_security_group_rules(self, security_group_id):
return True
self.firewall_driver.refresh_security_group_rules(security_group_id)
def refresh_security_group_members(self, security_group_id):
return True
self.firewall_driver.refresh_security_group_members(security_group_id)
def refresh_instance_security_rules(self, instance):
return True
self.firewall_driver.refresh_rules(instance)
def refresh_provider_fw_rules(self):
pass
self.firewall_driver.refresh_provider_fw_rules()
def get_available_resource(self, nodename):
"""Updates compute manager resource info on ComputeNode table.
@ -251,7 +246,7 @@ class LXDDriver(driver.ComputeDriver):
data["supported_instances"] = jsonutils.dumps([
('i686', 'lxd', 'lxd'),
('x86_64', 'lxd', 'lxd')])
data["vcpus"] = psutil.cpu_count()
data["vcpus"] = 4
data["memory_mb"] = memory['total'] / units.Mi
data["local_gb"] = disk['total'] / units.Gi
data["vcpus_used"] = 1
@ -267,47 +262,11 @@ class LXDDriver(driver.ComputeDriver):
return data
def ensure_filtering_rules_for_instance(self, instance_ref, network_info):
return
def get_instance_disk_info(self, instance, block_device_info=None):
return
def live_migration(self, context, instance_ref, dest,
post_method, recover_method, block_migration=False,
migrate_data=None):
post_method(context, instance_ref, dest, block_migration,
migrate_data)
return
def check_can_live_migrate_destination_cleanup(self, ctxt,
dest_check_data):
return
def check_can_live_migrate_destination(self, ctxt, instance_ref,
src_compute_info, dst_compute_info,
block_migration=False,
disk_over_commit=False):
return {}
def check_can_live_migrate_source(self, ctxt, instance_ref,
dest_check_data, block_device_info=None):
return
def finish_migration(self, context, migration, instance, disk_info,
network_info, image_meta, resize_instance,
block_device_info=None, power_on=True):
return
def confirm_migration(self, migration, instance, network_info):
return
def pre_live_migration(self, context, instance_ref, block_device_info,
network_info, disk, migrate_data=None):
return
self.firewall_driver.setup_basic_filtering(instance, network_info)
self.firewall_driver.prepare_instance_filter(instance, network_info)
def unfilter_instance(self, instance_ref, network_info):
return
self.firewall_driver.unfilter_instance(instance, network_info)
def get_available_nodes(self, refresh=False):
hostname = socket.gethostname()

View File

@ -4,7 +4,7 @@
pbr>=0.6,!=0.7,<1.0
Babel>=1.3
requests
oslo.concurrency
oslo.utils
oslo.i18n
requests>=2.2.0,!=2.4.0
oslo.concurrency>=0.3.0 # Apache-2.0
oslo.utils>=1.2.0 # Apache-2.0
oslo.i18n>=1.0.0 # Apache-2.0

View File

@ -17,6 +17,14 @@
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr'],
pbr=True)
pbr=True)

View File

@ -6,10 +6,10 @@ hacking>=0.9.2,<0.10
coverage>=3.6
discover
python-subunit
sphinx>=1.1.2
oslosphinx
oslotest>=1.1.0.0a1
python-subunit>=0.0.18
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
oslosphinx>=2.2.0 # Apache-2.0
oslotest>=1.2.0 # Apache-2.0
testrepository>=0.0.18
testscenarios>=0.4
testtools>=0.9.34
testtools>=0.9.36,!=1.2.0