0.2 changes

Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short 2015-03-03 13:08:50 -05:00
parent 5c134e6779
commit 243f30539b
11 changed files with 136 additions and 609 deletions

View File

@ -24,18 +24,7 @@ function configure_lxd {
sudo apt-add-repository -y ppa:ubuntu-lxc/lxd-daily
apt_get update
install_package lxd lxc-dev
setfacl -m nova:rx /var/lib/lxd/lxd
if [[ ! -d /var/lib/lxd ]]; then
sudo mkdir -p /var/lib/lxd/
sudo chown $USER:$USER /var/lib/lxd
fi
run_process lxd "$LXD_BIN_DIR/lxd/lxd --tcp $HOST_IP:8443 --debug"
echo "Configure LXD API"
}
function install_lxd {
git_clone $LXC_REPO $LXC_DIR

View File

@ -1,113 +0,0 @@
#!/usr/bin/python
"""
Manage edits to lxc-usernet(5) style file (/etc/lxc/lxc-usernet).
File is
* comment lines (#)
* <username> <type> <bridge> <count>
# USERNAME TYPE BRIDGE COUNT
ubuntu veth br100 128
"""
from oslo_concurrency import lockutils
ETC_LXC_USERNET = "/etc/lxc/lxc-usernet"
class UserNetLine(object):
def __init__(self, line):
self.error = None
cpos = line.find("#")
if cpos < 0:
payload = line.strip()
comment = None
else:
payload = line[:cpos].strip()
comment = line[cpos:]
if payload:
try:
user, ntype, brname, count = split(payload)
except ValueError:
# don't understand this line.
user, ntype, brname, count = None
self.error = line
else:
user, ntype, brname, count = None
self.user = user
self.ntype = ntype
self.bridge = brname
self.comment = comment
def __str__(self):
if self.error is not None:
return self.error
comment = ""
if self.comment is not None:
if self.user:
comm = " " + self.comment
else:
comm = self.comment
return ' '.join(self.user, self.ntype, self.bridge,
self.count + comm)
def update_usernet(user, bridge, op, if_type="veth",
count=1, require=True, fname=ETC_LXC_USERNET):
ops = ("set", "inc", "dec")
if op not in ops:
raise TypeError("op = '%s'. must be one of %s",
(op, ','.join(ops)))
minfo = "user=%s, bridge=%s, if_type=%s" % (user, bridge, if_type)
with lockutils.lock(str(fname)):
lines = load_usernet(fname)
found = []
for i, l in enumerate(lines):
if (user != l.user or bridge != l.bridge or l.ntype != if_type):
continue
found.append(i)
if found:
# update the last one (others deleted on write)
line = lines(found[-1])
if op == "inc":
line.count = int(count) + int(line.count)
elif op == "dec":
line.count = int(count) - int(line.count)
elif op == "set":
line.count = count
if require and not found and op != "set":
raise ValueError("EntryNotFound: %s" % minfo)
elif op == "set":
mline = UserNetLine("")
mline.user = user
mline.ntype = if_type
mline.bridge = bridge
mline.count = int(count)
tf = None
try:
tf = tempfile.NamedTemporaryFile(dir=os.path.dirname(fname),
delete=False)
for i, l in enumerate(lines):
if i in found[:-1]:
continue
else:
tf.write(l + "\n")
tf.close()
os.rename(tf.name, fname)
except Exception as e:
if tf is not None:
os.unlink(tf.name)
raise e
if __name__ == '__main__':
import sys
sys.exit(main())

View File

@ -17,10 +17,15 @@ import socket
from eventlet.green import httplib
from oslo_log import log as logging
from oslo.config import cfg
from nova.i18n import _
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class UnixHTTPConnection(httplib.HTTPConnection):
def __init__(self, path, host='localhost', port=None, strict=None,
@ -69,14 +74,24 @@ class Client(object):
def state(self, name):
(status, data) = self._make_request('GET', '/1.0/containers/%s/state' % name)
if status == 150:
return 'PENDING'
if status == 500:
return 'UNKNOWN'
if status == 200:
return data['metadata']['state']
def list(self):
(status, data) = self._make_request('GET', '/1.0/list')
(status, data) = self._make_request('GET', '/1.0')
if status != 200:
return []
return [container.split('/1.0/list')[-1] for container in data['metadata']]
return [container.split('/1.0')[-1] for container in data['metadata']]
def update_container(self, instance, config):
container_update = False
(status, data) = self._make_request('PUT', '/1.0/containers/%s' % instance, json.dumps(config))
if status != 200:
raise Exception('Failed to update configuration')
def start(self, name):
container_start = False
@ -134,14 +149,29 @@ class Client(object):
(status, data) = self._make_request('GET', '/1.0/images')
return [image.split('/1.0/images')[-1] for image in data['metadata']]
def upload_image(self, path, filename):
(status, data) = self._make_request('POST', '/1.0/images', open(path, 'rb'))
if status != 200:
raise Exception('Failed to upload image')
def remove_image(self, fingerprint):
(status, data) = self._make_request('DELETE', '/1.0/images/%s' % fingerprint)
if status != 200:
raise Exception('Failed to delete image')
def list_aliases(self):
status, data = self._make_request('/1.0/images/aliases')
return [alias.split('/1.0/aliases')[-1] for alias in data['metadata']]
(status, data) = self._make_request('GET', '/1.0/images/aliases')
return [alias.split('/1.0/images/aliases')[-1] for alias in data['metadata']]
def create_alias(self, alias, fingerprint):
container_alias = False
action = {'target': fingerprint,
'name': alias}
(status, data) = self._make_request('POST','/1.0/images/aliases', json.dumps(action))
return data
def alias_create(self, name, target):
payload = {'target': target,
'name': name}
(status, data) = self._make_request('POST', '/1.0/images/aliases', json.dumps(payload))
if status != 200:
raise Exception('Alias create failed')
def alias_delete(self, name):
(status, data) = self._make_request('DELETE', '/1.0/images/aliases/%s' % name)
if status != 200:
raise Exception('Failed to delete alias')

View File

@ -12,118 +12,54 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import os
import jinja2
from oslo.config import cfg
from oslo_log import log as logging
from nova.i18n import _LW, _
from nova import exception
from nova import utils
from . import utils as container_utils
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def get_container_console(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance['uuid'],
'container.console')
class LXDSetConfig(object):
def __init__(self, container, instance, image_meta, network_info):
self.container = container
def __init__(self, config, instance, image_meta, network_info):
self.instance = instance
self.config = config
self.image_meta = image_meta
self.network_info = network_info
self.config = {}
self.image = {}
self.raw_lxc = {}
def write_config(self):
lxc_template = self.get_lxd_template()
if lxc_template:
net = self.config_lxd_network()
(user, uoffset) = container_utils.parse_subfile(CONF.lxd.lxd_default_user,
'/etc/subuid')
(group, goffset) = container_utils.parse_subfile(CONF.lxd.lxd_default_user,
'/etc/subgid')
self.config = {
'lxd_common_config': '%s/%s.common.conf' % (CONF.lxd.lxd_config_dir,
lxc_template),
'lxd_userns_config': '%s/%s.userns.conf' % (CONF.lxd.lxd_config_dir,
lxc_template),
'lxd_rootfs': self.config_lxd_rootfs(),
'lxd_name': self.config_lxd_name(),
'lxd_logfile': self.config_lxd_logging(),
'lxd_console_file': self.config_lxd_console(),
'lxd_mac_addr': net['mac'],
'lxd_network_link': net['link'],
'lxd_user': user,
'lxd_uoffset': uoffset,
'lxd_group': group,
'lxd_goffset': goffset
}
self._get_lxd_config()
self.config['config'] = self.raw_lxc
self.config['source'] = self.image
tmpl_path, tmpl_file = os.path.split(CONF.lxd.lxd_config_template)
env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path),
trim_blocks=True)
template = env.get_template(tmpl_file)
tmpl = template.render(self.config)
config_file = container_utils.get_container_config(self.instance)
f = open(config_file, 'w')
f.write(tmpl)
f.close()
return self.config
def config_lxd_name(self):
if self.instance:
return self.instance['uuid']
def _get_lxd_config(self):
# Specify the console
console_log = 'lxc.console.logfile = %s\n' % get_container_console(self.instance)
self.raw_lxc['lxc.raw'] = console_log
def config_lxd_rootfs(self):
container_rootfs = container_utils.get_container_rootfs(self.instance)
if not os.path.exists(container_rootfs):
msg = _('Container rootfs not found')
raise exception.InstanceNotReady(msg)
return container_rootfs
def config_lxd_logging(self):
return container_utils.get_container_logfile(self.instance)
def config_lxd_network(self):
net = {}
if self.network_info:
# NOTE(jamespage) this does not deal with multiple nics.
for vif in self.network_info:
vif_id = vif['id'][:11]
vif_type = vif['type']
bridge = vif['network']['bridge']
mac = vif['address']
# Specify the network
for vif in self.network_info:
vif_id = vif['id'][:11]
vif_type = vif['type']
bridge = vif['network']['bridge']
mac = vif['address']
if vif_type == 'ovs':
bridge = 'qbr%s' % vif_id
net = {'mac': mac,
'link': bridge}
return net
self.raw_lxc['lxc.raw'] += 'lxc.network.type = veth\n'
self.raw_lxc['lxc.raw'] += 'lxc.network.addr = %s\n' % mac
self.raw_lxc['lxc.raw'] += 'lxc.network.link = %s\n' % bridge
def config_lxd_console(self):
return container_utils.get_container_console(self.instance)
def config_lxd_limits(self):
pass
def get_lxd_template(self):
LOG.debug('Fetching LXC template')
templates = []
if (self.image_meta and
self.image_meta.get('properties', {}).get('template')):
lxc_template = self.image_meta['properties'].get('template')
else:
lxc_template = CONF.lxd.lxd_default_template
path = os.listdir(CONF.lxd.lxd_template_dir)
for line in path:
templates.append(line.replace('lxc-', ''))
if lxc_template in templates:
return lxc_template
self.image = {'type': 'image', 'alias': self.instance['image_ref']}

View File

@ -14,11 +14,9 @@
import os
import lxc
from oslo.config import cfg
from oslo_log import log as logging
from oslo.utils import units, excutils
from oslo.utils import units
from nova.i18n import _, _LW, _LE, _LI
from nova import utils
@ -26,7 +24,6 @@ from nova import exception
from nova.compute import power_state
from . import config
from . import utils as container_utils
from . import vif
from . import images
@ -34,6 +31,7 @@ CONF = cfg.CONF
CONF.import_opt('use_cow_images', 'nova.virt.driver')
CONF.import_opt('vif_plugging_timeout', 'nova.virt.driver')
CONF.import_opt('vif_plugging_is_fatal', 'nova.virt.driver')
LOG = logging.getLogger(__name__)
MAX_CONSOLE_BYTES = 100 * units.Ki
@ -47,9 +45,11 @@ LXD_POWER_STATES = {
'FREEZING': power_state.PAUSED,
'FROZEN': power_state.SUSPENDED,
'THAWED': power_state.PAUSED,
'NONE': power_state.NOSTATE
'PENDING': power_state.BUILDING,
'UNKNOWN': power_state.NOSTATE
}
class Container(object):
def __init__(self, client, virtapi, firewall):
@ -57,7 +57,9 @@ class Container(object):
self.virtapi = virtapi
self.firewall_driver = firewall
self.vif_driver = vif.LXDGenericDriver()
self.config = {}
def init_container(self):
if not os.path.exists(CONF.lxd.lxd_socket):
@ -68,8 +70,7 @@ class Container(object):
console_log = os.path.join(CONF.lxd.lxd_root_dir,
instance['uuid'],
'container.console')
user = os.getuid()
utils.execute('chown', user, console_log, run_as_root=True)
with open(console_log, 'rb') as fp:
log_data, remaining = utils.last_bytes(fp, MAX_CONSOLE_BYTES)
if remaining > 0:
@ -82,24 +83,15 @@ class Container(object):
admin_password, network_info, block_device_info, flavor):
LOG.info(_LI('Starting new instance'), instance=instance)
try:
# Setup the LXC instance
instance_name = instance['uuid']
container = lxc.Container(instance_name)
container.set_config_path(CONF.lxd.lxd_root_dir)
# Setup the LXC instance
''' Fetch the image from glance '''
self._fetch_image(context, instance, image_meta)
''' Fetch the image from glance '''
self._fetch_image(context, instance, image_meta)
''' Set up the configuration file '''
self._write_config(instance, network_info, image_meta)
''' Set up the configuration file '''
#self._write_config(container, instance, network_info, image_meta)
''' Start the container '''
#self._start_container(context, instance, network_info, image_meta)
except Exception as ex:
with excutils.save_and_reraise_exception():
self.destroy_container(context, instance, network_info,
block_device_info)
''' Start the container '''
#self._start_container(context, instance, network_info, image_meta)
def destroy_container(self, context, instance, network_info, block_device_info,
destroy_disks=None, migrate_data=None):
@ -108,29 +100,19 @@ class Container(object):
self.teardown_network(instance, network_info)
def get_container_info(self, instance):
instance_name = instance['uuid']
container = lxc.Container(instance_name)
container.set_config_path(CONF.lxd.lxd_root_dir)
try:
mem = int(container.get_cgroup_item('memory.usage_in_bytes')) / units.Mi
except KeyError:
mem = 0
container_state = self.client.state(instance_name)
container_state = self.client.state(instance['uuid'])
if container_state is None:
container_state = 'NONE'
state = power_state.CRASHED
else:
state = LXD_POWER_STATES[container_state]
LOG.info(_('!!! %s') % container_state)
return {'state': LXD_POWER_STATES[container_state],
'mem': mem,
return {'state': state,
'mem': 0,
'cpu': 1}
def _fetch_image(self, context, instance, image_meta):
image = images.ContainerImage(context, instance, image_meta, self.client)
image.create_container()
image.upload_image()
def _start_container(self, context, instance, network_info, image_meta):
timeout = CONF.vif_plugging_timeout
@ -153,10 +135,10 @@ class Container(object):
self.client.start(instance['uuid'])
def _write_config(self, container, instance, network_info, image_meta):
self.config = config.LXDSetConfig(container, instance,
image_meta, network_info)
self.config.write_config()
def _write_config(self, instance, network_info, image_meta):
cconfig = config.LXDSetConfig(self.config, instance, image_meta, network_info)
self.config = cconfig.write_config()
self.client.update_container(instance['uuid'], self.config)
def _start_network(self, instance, network_info):
for vif in network_info:

View File

@ -57,22 +57,7 @@ lxd_opts = [
help='Default LXD unix socket'),
cfg.StrOpt('lxd_root_dir',
default='/var/lib/lxd/lxc',
help='Default LXD directory'),
cfg.StrOpt('lxd_default_template',
default='ubuntu-cloud',
help='Default LXC template'),
cfg.StrOpt('lxd_config_template',
default='/etc/lxd/lxd.template',
help='container config template'),
cfg.StrOpt('lxd_template_dir',
default='/usr/share/lxc/templates',
help='Default template directory'),
cfg.StrOpt('lxd_config_dir',
default='/usr/share/lxc/config',
help='Default lxc config dir'),
cfg.StrOpt('lxd_default_user',
default='root',
help='Default LXD user')
help='Default LXD directory')
]

View File

@ -15,14 +15,11 @@
import os
import hashlib
from oslo.config import cfg
from oslo_log import log as logging
from oslo.utils import units, excutils
from oslo_utils import excutils
from nova import utils
from nova.i18n import _, _LI
from nova.i18n import _, _LE
from nova.openstack.common import fileutils
from nova.virt import images
from nova import exception
@ -48,7 +45,7 @@ class ContainerImage(object):
if not os.path.exists(self.base_dir):
fileutils.ensure_tree(self.base_dir)
def create_container(self):
def upload_image(self):
LOG.info(_('Downloading image from glance'))
disk_format = self.image_meta.get('disk_format')
@ -56,33 +53,47 @@ class ContainerImage(object):
msg = _('Unable to determine disk format for image.')
raise exception.InvalidImageRef(msg)
if not os.path.exists(self.container_image):
LOG.info(_('Fetching Image from Glance'))
try:
images.fetch_to_raw(self.context, self.instance['image_ref'], self.container_image,
self.instance['user_id'], self.instance['project_id'],
max_size=self.max_size)
fingerprint = self._get_fingerprint()
if fingerprint in self.client.list_images():
msg = _('Image already exists in LXD store')
raise exception.InvalidImageRef(msg)
self.client.upload_image(self.container_image, self.container_image.split('/')[-1])
if self.instance['image_ref'] in self.client.list_aliases():
msg = _('Alias already exists in LXD store')
raise exception.InvalidImageRef(msg)
self.client.alias_create(self.instance['image_ref'], fingerprint)
os.unlink(self.container_image)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Erorr uploading image to image store for %(image).'),
{'image': self.instance['image_ref']})
self.cleanup_image()
def cleanup_image(self):
LOG.info(_('Cleaning up image'))
if os.path.exists(self.container_image):
return
fingerprint = self._get_fingerprint()
os.unlink(self.container_image)
LOG.info(_('Fetching Image from Glance'))
images.fetch_to_raw(self.context, self.instance['image_ref'], self.container_image,
self.instance['user_id'], self.instance['project_id'],
max_size=self.max_size)
if self.instance['image_ref'] in self.client.lists_aliases():
self.client.alias_delete(self.instance['image_ref'])
fingerprint = self._get_fingerprint(self.container_image)
if fingerprint is not None:
self.client.remove_image(fingerprint)
if fingerprint in self.client.list_images():
msg = _('Image already exists in image store')
raise exception.InvalidImageRef(msg)
alias = 'glance/%s' % self.instance['image_ref']
if alias in self.client.list_aliases():
msg = _('Alias already exists')
raise exception.ImageUnacceptable(msg)
data = self.client.create_alias(alias, fingerprint)
LOG.info(_('!!! %s') % data)
os.unlink(self.container_image)
def _get_fingerprint(self, filename):
m = hashlib.sha256()
with open(filename, 'rb') as f:
for chunk in iter(lambda: f.read(128 * m.block_size), b''):
m.update(chunk)
return m.hexdigest()
def _get_fingerprint(self):
with open(self.container_image, 'rb') as fp:
fingerprint = hashlib.sha256(fp.read()).hexdigest()
return fingerprint

View File

@ -1,219 +0,0 @@
# Copyright (c) 2014 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Manage edits to lxc-usernet(5) style file (/etc/lxc/lxc-usernet).
File is
* comment lines (#)
* <username> <type> <bridge> <count>
example:
# USERNAME TYPE BRIDGE COUNT
ubuntu veth br100 128
"""
import os
import argparse
import tempfile
from oslo_concurrency import lockutils
ETC_LXC_USERNET = "/etc/lxc/lxc-usernet"
class UserNetLine(object):
def __init__(self, line):
self.error = None
line = line.rstrip("\n")
cpos = line.find("#")
user = None
ntype = None
brname = None
count = None
if cpos < 0:
payload = line.strip()
comment = None
else:
payload = line[:cpos].strip()
comment = line[cpos:]
if payload:
try:
user, ntype, brname, count = payload.split()
except ValueError:
# don't understand this line.
self.error = line
else:
comment = line
self.user = user
self.bridge = brname
self.ntype = ntype
self.count = count
self.comment = comment
def __repr__(self):
return(self.__str__())
def __str__(self):
if self.error is not None:
return self.error
if self.user:
comm = ""
if self.comment:
comm = " " + self.comment
return ("%s %s %s %s" % (self.user, self.ntype, self.bridge,
str(self.count) + comm))
return self.comment
def load_usernet(fname):
lines = []
with open(fname, "r") as fp:
for line in fp:
lines.append(UserNetLine(line))
return lines
def write_usernet(fname, lines, drop=None):
if drop:
nlines = []
for i, l in enumerate(lines):
if i not in drop:
nlines.append(l)
lines = nlines
tf = None
try:
tf = tempfile.NamedTemporaryFile(dir=os.path.dirname(fname),
delete=False)
for l in lines:
tf.write(str(l) + "\n")
tf.close()
if os.path.isfile(fname):
statl = os.stat(fname)
os.chmod(tf.name, statl.st_mode)
os.chown(tf.name, statl.st_uid, statl.st_gid)
else:
os.chmod(tf.name, 0o644)
os.rename(tf.name, fname)
finally:
if tf is not None and os.path.isfile(tf.name):
os.unlink(tf.name)
def update_usernet(user, bridge, op, count=1, ntype="veth",
strict=False, fname=ETC_LXC_USERNET):
ops = ("set", "inc", "dec")
if op not in ops:
raise TypeError("op = '%s'. must be one of %s",
(op, ','.join(ops)))
minfo = "user=%s, bridge=%s, ntype=%s" % (user, bridge, ntype)
lines = load_usernet(fname)
found = []
for i, l in enumerate(lines):
if (user != l.user or bridge != l.bridge or l.ntype != ntype):
continue
found.append(i)
if strict and not found and op != "set":
raise ValueError("EntryNotFound: %s" % minfo)
if not found:
if op == "dec":
# decrement non-existing, assume zero
return
newline = UserNetLine("")
newline.user = user
newline.ntype = ntype
newline.bridge = bridge
newline.count = int(count)
lines.append(newline)
else:
# update the last one (others deleted on write)
line = lines[found[-1]]
if op == "inc":
line.count = int(line.count) + int(count)
elif op == "dec":
line.count = int(line.count) - int(count)
elif op == "set":
if len(found) == 1 and line.count == count and count != 0:
return
line.count = count
if line.count == 0:
# set or dec to '0'. add this line to found, for delete
found.append(found[-1])
write_usernet(fname, lines, found[:-1])
def lfilter(fname, user=None, bridge=None, count=None, ntype="veth"):
ret = []
for f in load_usernet(fname):
if user is not None and f.user != user:
continue
if bridge is not None and f.bridge != bridge:
continue
if count is not None and str(f.count) != str(count):
continue
if ntype is not None and f.ntype != ntype:
continue
ret.append(f)
return ret
def manage_main():
fname = ETC_LXC_USERNET
parser = argparse.ArgumentParser()
parser.add_argument("--type", "-t", help="nic type (default: 'veth')",
default="veth", dest="ntype")
parser.add_argument(
'operation',
choices=(
"set",
"inc",
"dec",
"del",
"get"))
parser.add_argument('user', help="username")
parser.add_argument('bridge', help="bridge")
parser.add_argument('count', nargs="?", help="number to operate with.",
default=None, const=int)
args = parser.parse_args()
if args.operation == "del":
args.operation = "set"
args.count = 0
elif args.operation in ("set", "inc", "dec") and args.count is None:
args.count = 1
if args.operation == "get":
if args.bridge == "*":
args.bridge = None
matching = lfilter(fname, user=args.user, bridge=args.bridge,
count=args.count, ntype=args.ntype)
for l in matching:
print(str(l))
return 0
with lockutils.lock(str(fname)):
update_usernet(user=args.user, bridge=args.bridge, op=args.operation,
count=args.count, ntype=args.ntype, fname=fname)

View File

@ -1,69 +0,0 @@
# Copyright (c) 2014 Canonical ltd
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import grp
import getpass
import pwd
import os
from oslo.config import cfg
from oslo_log import log as logging
from nova.i18n import _
from nova import context as nova_context
from nova import objects
from nova import utils
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
def write_lxc_usernet(instance, bridge, user=None, count=1):
if user is None:
user = CONF.lxd.lxd_default_user
utils.execute('lxc-usernet-manage', 'set', user, bridge, str(count),
run_as_root=True, check_exit_code=[0])
def parse_subfile(name, fname):
line = None
with open(fname, "r") as fp:
for cline in fp:
if cline.startswith(name + ":"):
line = cline
break
if line is None:
raise ValueError("%s not found in %s" % (name, fname))
toks = line.split(":")
return (toks[1], toks[2])
def get_container_config(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance['uuid'], 'config')
def get_container_rootfs(instance):
return os.path.join(CONF.lxd.lxd_root_dir,instance['uuid'], 'rootfs')
def get_container_logfile(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance['uuid'],
'container.logfile')
def get_container_console(instance):
return os.path.join(CONF.lxd.lxd_root_dir, instance['uuid'],
'container.console')

View File

@ -24,12 +24,9 @@ from oslo_concurrency import processutils
from nova.i18n import _LW
from nova import exception
from nova import utils
from nova.openstack.common import log as logging
from nova.network import linux_net
from nova.network import model as network_model
import utils as container_utils
CONF = cfg.CONF
@ -84,8 +81,6 @@ class LXDOpenVswitchDriver(object):
v2_name, iface_id, vif['address'],
instance['uuid'])
container_utils.write_lxc_usernet(instance, br_name)
def unplug(self, instance, vif):
try:
br_name = self._get_br_name(vif['id'])

View File

@ -10,4 +10,4 @@ oslo.concurrency>=1.4.1 # Apache-2.0
oslo.utils>=1.2.0 # Apache-2.0
oslo.i18n>=1.3.0 # Apache-2.0
oslo.log
python-glanceclient>=0.15.0
eventlet