Misc fixes
Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
parent
c299f10b7e
commit
4012906bae
|
@ -0,0 +1 @@
|
|||
__import__('pkg_resources').declare_namespace(__name__)
|
|
@ -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)
|
||||
|
@ -65,6 +69,34 @@ class Client(object):
|
|||
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):
|
||||
containers = []
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
8
setup.py
8
setup.py
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue