Merge lp:~zulcss/nova/lxc into lp:~ubuntu-server-dev/nova/havana

Proposed by Chuck Short
Status: Merged
Approved by: Chuck Short
Approved revision: 625
Merged at revision: 621
Proposed branch: lp:~zulcss/nova/lxc
Merge into: lp:~ubuntu-server-dev/nova/havana
Diff against target: 814 lines (+791/-0)
3 files modified
debian/changelog (+2/-0)
debian/patches/native-lxc-hypervisor.patch (+788/-0)
debian/patches/series (+1/-0)
To merge this branch: bzr merge lp:~zulcss/nova/lxc
Reviewer Review Type Date Requested Status
James Page Approve
Chuck Short (community) Needs Resubmitting
Adam Gandelman (community) Needs Fixing
Review via email: mp+187796@code.launchpad.net

Description of the change

Adds native lxc driver.

To post a comment you must log in.
Revision history for this message
Adam Gandelman (gandelman-a) wrote :

Can you please cleanup pep8 and add unit tests?

I'm concerned shipping this before its even been proposed upstream, especially if its not shipping without any test coverage. I'd be okay if it had tests run at package build time and you also integrated this driver as something we deploy and exercise as part of lp:openstack-ubuntu-testing.

review: Needs Fixing
lp:~zulcss/nova/lxc updated
621. By Chuck Short

Updated native-lxc-hypervisor.patch

Revision history for this message
Chuck Short (zulcss) wrote :

> Can you please cleanup pep8 and add unit tests?
>
> I'm concerned shipping this before its even been proposed upstream, especially
> if its not shipping without any test coverage. I'd be okay if it had tests
> run at package build time and you also integrated this driver as something we
> deploy and exercise as part of lp:openstack-ubuntu-testing.

- Added basic testsuite
- Fixed up pep8

review: Needs Resubmitting
Revision history for this message
James Page (james-page) wrote :

${PYTHON:-python} -m subunit.run discover -t ./ ./nova/tests
======================================================================
FAIL: nova.tests.virt.lxc.test_driver.LXCDriverTestCase.test_get_host_stats
tags: worker-0
----------------------------------------------------------------------
Empty attachments:
  pythonlogging:''
  stderr
  stdout

Traceback (most recent call last):
  File "/«PKGBUILDDIR»/nova/tests/virt/lxc/test_driver.py", line 123, in test_get_host_stats
    host_stats = self.lxc_connection.get_host_stats()
  File "/«PKGBUILDDIR»/nova/virt/lxc/driver.py", line 145, in get_host_stats
    return self.hostops.get_host_stats(refresh)
  File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 43, in get_host_stats
    self._update_stats()
  File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 69, in _update_stats
    disk = self._get_disk_info()
  File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 110, in _get_disk_info
    hddinfo = os.statvfs(CONF.lxc_path)
OSError: [Errno 2] No such file or directory: '/var/lib/lxc'

review: Needs Fixing
lp:~zulcss/nova/lxc updated
622. By Chuck Short

Update patch again

Revision history for this message
Chuck Short (zulcss) wrote :

> ${PYTHON:-python} -m subunit.run discover -t ./ ./nova/tests
> ======================================================================
> FAIL: nova.tests.virt.lxc.test_driver.LXCDriverTestCase.test_get_host_stats
> tags: worker-0
> ----------------------------------------------------------------------
> Empty attachments:
> pythonlogging:''
> stderr
> stdout
>
> Traceback (most recent call last):
> File "/«PKGBUILDDIR»/nova/tests/virt/lxc/test_driver.py", line 123, in
> test_get_host_stats
> host_stats = self.lxc_connection.get_host_stats()
> File "/«PKGBUILDDIR»/nova/virt/lxc/driver.py", line 145, in get_host_stats
> return self.hostops.get_host_stats(refresh)
> File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 43, in get_host_stats
> self._update_stats()
> File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 69, in _update_stats
> disk = self._get_disk_info()
> File "/«PKGBUILDDIR»/nova/virt/lxc/hostops.py", line 110, in _get_disk_info
> hddinfo = os.statvfs(CONF.lxc_path)
> OSError: [Errno 2] No such file or directory: '/var/lib/lxc'

Fixed

Revision history for this message
James Page (james-page) wrote :

OK _ test suite now runs successfully in a sbuild.

My only other comments is that some DEP headers on the patch would be good.

review: Needs Fixing
lp:~zulcss/nova/lxc updated
623. By Chuck Short

Add dep8 headers

Revision history for this message
James Page (james-page) wrote :

+Forwarded: Yes

Please could you reference the gerrit topic or suchlike - makes it easier for someone else to track upstream activity.

review: Needs Fixing
lp:~zulcss/nova/lxc updated
624. By Chuck Short

Update dep8

625. By Chuck Short

Update patch

Revision history for this message
James Page (james-page) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2013-09-19 19:50:37 +0000
3+++ debian/changelog 2013-10-02 17:10:37 +0000
4@@ -17,6 +17,8 @@
5 python-boto, python-paramiko, python-amplib, python-eventlet,
6 python-glanceclient, python-oslo.config, python-paramiko, python-six
7 * debian/patches/fix-requirements.patch: Rediffed
8+ * debian/patches/native-lxc-hypervisor.patch: Add native lxc support.
9+ (LP: #1220701)
10
11 -- Chuck Short <zulcss@ubuntu.com> Fri, 13 Sep 2013 10:12:52 -0400
12
13
14=== added file 'debian/patches/native-lxc-hypervisor.patch'
15--- debian/patches/native-lxc-hypervisor.patch 1970-01-01 00:00:00 +0000
16+++ debian/patches/native-lxc-hypervisor.patch 2013-10-02 17:10:37 +0000
17@@ -0,0 +1,788 @@
18+Description: Add native LXC support for openstack
19+Author: Chuck Short <zulcss@ubuntu.com>
20+Forwarded: no, https://github.com/zulcss/nova
21+diff -Naurp nova/etc/nova/nova.conf.sample nova.lxc/etc/nova/nova.conf.sample
22+--- nova/etc/nova/nova.conf.sample 2013-09-30 23:23:16.952467626 -0400
23++++ nova.lxc/etc/nova/nova.conf.sample 2013-09-30 21:32:00.748464388 -0400
24+@@ -2202,6 +2202,23 @@
25+
26+
27+ #
28++# Options defined in nova.virt.lxc.driver
29++#
30++
31++# Default lxc configuration path (string value)
32++#lxc_path=/var/lib/lxc
33++
34++# Default cgroups path (string value)
35++#cgroups_path=/sys/fs/cgroup
36++
37++# Template file for lxc configuration file (string value)
38++#lxc_config_template=$pybasedir/nova/virt/lxc/config.tmpl
39++
40++# Template file for lxc fstab file (string value)
41++#lxc_fstab_template=$pybasedir/nova/virt/lxc/fstab.tmpl
42++
43++
44++#
45+ # Options defined in nova.virt.powervm.driver
46+ #
47+
48+diff -Naurp nova/etc/nova/rootwrap.d/compute.filters nova.lxc/etc/nova/rootwrap.d/compute.filters
49+--- nova/etc/nova/rootwrap.d/compute.filters 2013-09-30 23:23:16.952467626 -0400
50++++ nova.lxc/etc/nova/rootwrap.d/compute.filters 2013-09-30 12:51:46.540449253 -0400
51+@@ -209,3 +209,10 @@ rpc.mountd: CommandFilter, rpc.mountd, r
52+
53+ # nova/virt/libvirt/utils.py:
54+ rbd: CommandFilter, rbd, root
55++
56++# nova/virt/vmutils.py
57++lxc-info: CommandFilter, lxc-info, root
58++lxc-ls: CommandFilter, lxc-ls, root
59++lxc-start: CommandFilter, lxc-start, root
60++lxc-stop: CommandFilter, lxc-stop, root
61++lxc-destroy CommandFilter, lxc-destroy, root
62+diff -Naurp nova/nova/tests/virt/lxc/__init__.py nova.lxc/nova/tests/virt/lxc/__init__.py
63+--- nova/nova/tests/virt/lxc/__init__.py 1969-12-31 19:00:00.000000000 -0500
64++++ nova.lxc/nova/tests/virt/lxc/__init__.py 2013-09-30 12:52:48.900449283 -0400
65+@@ -0,0 +1,15 @@
66++# vim: tabstop=4 shiftwidth=4 softtabstop=4
67++
68++# Copyright (c) 2013 Canonical
69++#
70++# Licensed under the Apache License, Version 2.0 (the "License"); you may
71++# not use this file except in compliance with the License. You may obtain
72++# a copy of the License at
73++#
74++# http://www.apache.org/licenses/LICENSE-2.0
75++#
76++# Unless required by applicable law or agreed to in writing, software
77++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
78++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
79++# License for the specific language governing permissions and limitations
80++# under the License.
81+diff -Naurp nova/nova/tests/virt/lxc/test_driver.py nova.lxc/nova/tests/virt/lxc/test_driver.py
82+--- nova/nova/tests/virt/lxc/test_driver.py 1969-12-31 19:00:00.000000000 -0500
83++++ nova.lxc/nova/tests/virt/lxc/test_driver.py 2013-10-01 11:06:44.672830906 -0400
84+@@ -0,0 +1,126 @@
85++# vim: tabstop=4 shiftwidth=4 softtabstop=4
86++
87++# Copyright (c) 2013 Canonical
88++#
89++# Licensed under the Apache License, Version 2.0 (the "License"); you may
90++# not use this file except in compliance with the License. You may obtain
91++# a copy of the License at
92++#
93++# http://www.apache.org/licenses/LICENSE-2.0
94++#
95++# Unless required by applicable law or agreed to in writing, software
96++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
97++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
98++# License for the specific language governing permissions and limitations
99++# under the License.
100++
101++import fixtures
102++import mox
103++import os
104++
105++from nova.compute import flavors
106++from nova.compute import power_state
107++from nova import context
108++from nova import db
109++from nova.network import model as network_model
110++from nova import test
111++from nova.tests import fake_network_cache_model
112++from nova import utils
113++from nova.virt import images
114++from nova.virt.lxc import driver as lxc_connection
115++from nova.virt.lxc import vmutils
116++
117++
118++class LXCDriverTestCase(test.TestCase):
119++ def setUp(self):
120++ super(LXCDriverTestCase, self).setUp()
121++ self.flags(instances_path=self.useFixture(fixtures.TempDir()).path)
122++ self.lxc_connection = lxc_connection.LXCDriver(None)
123++
124++ instance_type = db.flavor_get(context.get_admin_context(), 5)
125++ sys_meta = flavors.save_flavor_info({}, instance_type)
126++
127++ self.instance = {
128++ 'uuid': '32dfcb37-5af1-552b-357c-be8c3aa38310',
129++ 'memory_kb': '1024000',
130++ 'basepath': '/some/path',
131++ 'bridge_name': 'br100',
132++ 'vcpus': 2,
133++ 'project_id': 'fake',
134++ 'bridge': 'br101',
135++ 'image_ref': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
136++ 'root_gb': 10,
137++ 'ephemeral_gb': 20,
138++ 'instance_type_id': '5', # m1.small
139++ 'extra_specs': {},
140++ 'system_metadata': sys_meta}
141++
142++ def test_get_info_containers_running(self):
143++ self.mox.StubOutWithMock(vmutils.VMUtils, 'container_exists')
144++ vmutils.VMUtils.container_exists(mox.IgnoreArg()).AndReturn(True)
145++ self.mox.ReplayAll()
146++ state = self.lxc_connection.get_info(self.instance)
147++ self.assertEqual(state['state'], power_state.RUNNING)
148++
149++ def test_get_info_containers_not_running(self):
150++ self.mox.StubOutWithMock(vmutils.VMUtils, 'container_exists')
151++ vmutils.VMUtils.container_exists(mox.IgnoreArg()).AndReturn(False)
152++ self.mox.ReplayAll()
153++ state = self.lxc_connection.get_info(self.instance)
154++ self.assertEqual(state['state'], power_state.SHUTDOWN)
155++
156++ def test_get_info_containers_no_status(self):
157++ self.mox.StubOutWithMock(vmutils.VMUtils, 'container_exists')
158++ vmutils.VMUtils.container_exists(mox.IgnoreArg()).AndReturn('')
159++ self.mox.ReplayAll()
160++ state = self.lxc_connection.get_info(self.instance)
161++ self.assertEqual(state['state'], power_state.NOSTATE)
162++
163++ def test_spawn(self):
164++ def fake_image_fetch(context, image_id, file_path,
165++ user_id, project_id):
166++ pass
167++
168++ self.stubs.Set(images, 'fetch', fake_image_fetch)
169++ image_meta = {}
170++ image_meta['id'] = '666'
171++ fake_net_info = network_model.NetworkInfo([
172++ fake_network_cache_model.new_vif()])
173++
174++ instance_ref = self.instance
175++ instance_ref['image_ref'] = 123456 # we send an int to test sha1 call
176++ instance_type = db.flavor_get(context.get_admin_context(),
177++ instance_ref['instance_type_id'])
178++ sys_meta = flavors.save_flavor_info({}, instance_type)
179++ instance_ref['system_metadata'] = sys_meta
180++ instance = db.instance_create(
181++ context.get_admin_context(), instance_ref)
182++
183++ self.lxc_connection.spawn(context.get_admin_context(),
184++ self.instance, image_meta, [], '',
185++ fake_net_info)
186++
187++ def test_get_console(self):
188++ with utils.tempdir() as tmpdir:
189++ self.flags(instances_path=tmpdir)
190++
191++ instance_ref = self.instance
192++ instance_ref['image_ref'] = 123456
193++ instance = db.instance_create(
194++ context.get_admin_context(), instance_ref)
195++
196++ console_dir = os.path.join(tmpdir, self.instance['uuid'])
197++ console_log = "%s/console.log" % console_dir
198++ os.makedirs(console_dir)
199++
200++ f = open(console_log, 'w')
201++ f.write('0123456789')
202++ f.close()
203++
204++ output = self.lxc_connection.get_console_output(self.instance)
205++
206++ self.assertEquals('0123456789', output)
207++
208++ def test_get_host_stats(self):
209++ host_stats = self.lxc_connection.get_host_stats()
210++ self.assertIsNotNone(host_stats)
211+diff -Naurp nova/nova/virt/lxc/config.tmpl nova.lxc/nova/virt/lxc/config.tmpl
212+--- nova/nova/virt/lxc/config.tmpl 1969-12-31 19:00:00.000000000 -0500
213++++ nova.lxc/nova/virt/lxc/config.tmpl 2013-09-30 12:51:46.540449253 -0400
214+@@ -0,0 +1,52 @@
215++# Template used to create this container: /usr/share/lxc/templates/lxc-ubuntu
216++# Parameters passed to the template:
217++lxc.network.type = veth
218++lxc.network.hwaddr = {{ container_hwaddr }}
219++lxc.network.flags = up
220++lxc.network.link = {{ container_link }}
221++lxc.rootfs = {{ container_rootfs }}
222++lxc.mount = {{ container_fstab }}
223++lxc.pivotdir = lxc_putold
224++
225++lxc.devttydir = lxc
226++lxc.tty = 4
227++lxc.pts = 1024
228++
229++lxc.utsname = {{ container_name }}
230++lxc.cap.drop = sys_module mac_admin mac_override sys_time
231++lxc.console = {{ console_file }}
232++
233++# When using LXC with apparmor, uncomment the next line to run unconfined:
234++lxc.aa_profile = unconfined
235++
236++# To support container nesting on an Ubuntu host, uncomment next two lines:
237++#lxc.aa_profile = lxc-container-default-with-nesting
238++#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
239++
240++lxc.cgroup.devices.deny = a
241++# Allow any mknod (but not using the node)
242++lxc.cgroup.devices.allow = c *:* m
243++lxc.cgroup.devices.allow = b *:* m
244++# /dev/null and zero
245++lxc.cgroup.devices.allow = c 1:3 rwm
246++lxc.cgroup.devices.allow = c 1:5 rwm
247++# consoles
248++lxc.cgroup.devices.allow = c 5:1 rwm
249++lxc.cgroup.devices.allow = c 5:0 rwm
250++# /dev/{,u}random
251++lxc.cgroup.devices.allow = c 1:9 rwm
252++lxc.cgroup.devices.allow = c 1:8 rwm
253++lxc.cgroup.devices.allow = c 136:* rwm
254++lxc.cgroup.devices.allow = c 5:2 rwm
255++# rtc
256++lxc.cgroup.devices.allow = c 254:0 rm
257++# fuse
258++lxc.cgroup.devices.allow = c 10:229 rwm
259++# tun
260++lxc.cgroup.devices.allow = c 10:200 rwm
261++# full
262++lxc.cgroup.devices.allow = c 1:7 rwm
263++# hpet
264++lxc.cgroup.devices.allow = c 10:228 rwm
265++# kvm
266++lxc.cgroup.devices.allow = c 10:232 rwm
267+diff -Naurp nova/nova/virt/lxc/driver.py nova.lxc/nova/virt/lxc/driver.py
268+--- nova/nova/virt/lxc/driver.py 1969-12-31 19:00:00.000000000 -0500
269++++ nova.lxc/nova/virt/lxc/driver.py 2013-09-30 21:17:31.856463967 -0400
270+@@ -0,0 +1,145 @@
271++# vim: tabstop=4 shiftwidth=4 softtabstop=4
272++
273++# Copyright 2010 United States Government as represented by the
274++# Administrator of the National Aeronautics and Space Administration.
275++# All Rights Reserved.
276++# Copyright (c) 2013 Canonical Ltd
277++#
278++# Licensed under the Apache License, Version 2.0 (the "License"); you may
279++# not use this file except in compliance with the License. You may obtain
280++# a copy of the License at
281++#
282++# http://www.apache.org/licenses/LICENSE-2.0
283++#
284++# Unless required by applicable law or agreed to in writing, software
285++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
286++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
287++# License for the specific language governing permissions and limitations
288++# under the License.
289++
290++"""
291++lxc hypervisor drvier
292++"""
293++
294++import os
295++
296++from oslo.config import cfg
297++
298++from nova.compute import power_state
299++from nova.openstack.common.gettextutils import _ # noqa
300++from nova.openstack.common import log as logging
301++from nova.virt import driver
302++from nova.virt.lxc import hostops
303++from nova.virt.lxc import vmops
304++from nova.virt import virtapi
305++
306++
307++lxc_opts = [
308++ cfg.StrOpt('lxc_path',
309++ default='/var/lib/lxc',
310++ help='Default lxc configuration path'),
311++ cfg.StrOpt('cgroups_path',
312++ default='/sys/fs/cgroup',
313++ help='Default cgroups path'),
314++ cfg.StrOpt('lxc_config_template',
315++ default='$pybasedir/nova/virt/lxc/config.tmpl',
316++ help='Template file for lxc configuration file'),
317++ cfg.StrOpt('lxc_fstab_template',
318++ default='$pybasedir/nova/virt/lxc/fstab.tmpl',
319++ help='Template file for lxc fstab file'),
320++ ]
321++
322++CONF = cfg.CONF
323++CONF.register_opts(lxc_opts)
324++CONF.import_opt('host', 'nova.netconf')
325++
326++LOG = logging.getLogger(__name__)
327++
328++
329++class LXCDriver(driver.ComputeDriver):
330++ capabilities = {
331++ "has_imagecache": False,
332++ "supports_recreate": False,
333++ }
334++
335++ """lxc hypervisor driver."""
336++
337++ def __init__(self, virtapi, read_only=False):
338++ super(LXCDriver, self).__init__(virtapi)
339++ self.hostops = hostops.HostOps()
340++ self.vmops = vmops.VMOps()
341++
342++ def init_host(self, host):
343++ if not os.path.exists("/usr/bin/lxc-version"):
344++ LOG.error(_('LXC is not installed'))
345++
346++ def list_instances(self):
347++ return self.vmops.list_instances()
348++
349++ def plug_vifs(self, instance, network_info):
350++ """Plug VIFs into networks."""
351++ pass
352++
353++ def unplug_vifs(self, instance, network_info):
354++ """Unplug VIFs from networks."""
355++ pass
356++
357++ def spawn(self, context, instance, image_meta, injected_files,
358++ admin_password, network_info=None, block_device_info=None):
359++ self.vmops.spawn(context, instance, image_meta, injected_files,
360++ admin_password, network_info, block_device_info)
361++
362++ def reboot(self, context, instance, network_info, reboot_type,
363++ block_device_info=None, bad_volumes_callback=None):
364++ pass
365++
366++ def power_off(self, instance):
367++ self.vmops.power_off(instance)
368++
369++ def power_on(self, context, instance, network_info, block_device_info):
370++ self.vmops.power_on(instance)
371++
372++ def restore(self, instance):
373++ pass
374++
375++ def pause(self, instance):
376++ pass
377++
378++ def unpause(self, instance):
379++ pass
380++
381++ def suspend(self, instance):
382++ pass
383++
384++ def resume(self, instance, network_info, block_device_info=None):
385++ pass
386++
387++ def destroy(self, instance, network_info, block_device_info=None,
388++ destroy_disks=True, context=None):
389++ self.vmops.destroy(instance, network_info, block_device_info,
390++ destroy_disks, context)
391++ self.virtapi.instance_update(context.get_admin_context(),
392++ instance['uuid'], {'power_state': power_state.SHUTDOWN})
393++
394++ def get_info(self, instance):
395++ state = self.vmops.container_exists(instance)
396++ if state:
397++ pstate = power_state.RUNNING
398++ elif state is False:
399++ pstate = power_state.SHUTDOWN
400++ else:
401++ pstate = power_state.NOSTATE
402++ return {'state': pstate,
403++ 'max_mem': 0,
404++ 'mem': 0,
405++ 'num_cpu': 2,
406++ 'cpu_time': 0}
407++
408++ def get_console_output(self, instance):
409++ return self.vmops.get_console_output(instance)
410++
411++ def get_available_resource(self, nodename):
412++ return self.hostops.get_compute_stats()
413++
414++ def get_host_stats(self, refresh=False):
415++ return self.hostops.get_host_stats(refresh)
416+diff -Naurp nova/nova/virt/lxc/fstab.tmpl nova.lxc/nova/virt/lxc/fstab.tmpl
417+--- nova/nova/virt/lxc/fstab.tmpl 1969-12-31 19:00:00.000000000 -0500
418++++ nova.lxc/nova/virt/lxc/fstab.tmpl 2013-09-30 12:51:46.540449253 -0400
419+@@ -0,0 +1,6 @@
420++proc proc proc nodev,noexec,nosuid 0 0
421++sysfs sys sysfs defaults 0 0
422++/sys/fs/fuse/connections sys/fs/fuse/connections none bind 0 0
423++/sys/kernel/debug sys/kernel/debug none bind 0 0
424++/sys/kernel/security sys/kernel/security none bind 0 0
425++/sys/fs/pstore sys/fs/pstore none bind 0 0
426+diff -Naurp nova/nova/virt/lxc/hostops.py nova.lxc/nova/virt/lxc/hostops.py
427+--- nova/nova/virt/lxc/hostops.py 1969-12-31 19:00:00.000000000 -0500
428++++ nova.lxc/nova/virt/lxc/hostops.py 2013-10-01 10:17:22.200760275 -0400
429+@@ -0,0 +1,132 @@
430++# vim: tabstop=4 shiftwidth=4 softtabstop=4
431++
432++# Copyright 2010 United States Government as represented by the
433++# Administrator of the National Aeronautics and Space Administration.
434++# All Rights Reserved.
435++# Copyright (c) 2013 Canonical Ltd
436++#
437++# Licensed under the Apache License, Version 2.0 (the "License"); you may
438++# not use this file except in compliance with the License. You may obtain
439++# a copy of the License at
440++#
441++# http://www.apache.org/licenses/LICENSE-2.0
442++#
443++# Unless required by applicable law or agreed to in writing, software
444++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
445++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
446++# License for the specific language governing permissions and limitations
447++# under the License.
448++
449++import multiprocessing
450++import os
451++import platform
452++import sys
453++
454++from oslo.config import cfg
455++
456++from nova.openstack.common.gettextutils import _ # noqa
457++from nova.openstack.common import jsonutils
458++from nova.openstack.common import log as logging
459++
460++
461++CONF = cfg.CONF
462++
463++log = logging.getLogger(__name__)
464++
465++
466++class HostOps(object):
467++ def __init__(self):
468++ self._stats = None
469++
470++ def get_host_stats(self, refresh=False):
471++ if refresh or not self._stats:
472++ self._update_stats()
473++ return self._stats
474++
475++ def get_compute_stats(self):
476++ # Updating host information
477++ disk = self. _get_disk_info()
478++ memory = self._get_host_memory()
479++
480++ dic = {'vcpus': 1,
481++ 'local_gb': disk['total'],
482++ 'vcpus_used': 0,
483++ 'memory_mb': memory['total'],
484++ 'memory_mb_used': memory['total'] - memory['free'],
485++ 'local_gb_used': disk['total'] - disk['free'],
486++ 'hypervisor_type': 'lxc',
487++ 'hypervisor_version': '1.0',
488++ 'hypervisor_hostname': platform.node(),
489++ 'cpu_info': '?',
490++ 'supported_instances': jsonutils.dumps([
491++ ('i686', 'lxc', 'lxc'),
492++ ('x86_64', 'lxc', 'lxc')]),
493++ }
494++ return dic
495++
496++ def _update_stats(self):
497++ memory = self._get_host_memory()
498++ disk = self._get_disk_info()
499++ cpu = self._get_cpu_info()
500++
501++ data = {}
502++ data["vpcus"] = 1
503++ data["cpu_info"] = \
504++ {'vendor': cpu['vendor'],
505++ 'model': cpu['features'],
506++ 'topology': {'cores': 1,
507++ 'socket': multiprocessing.cpu_count(),
508++ 'threads': 1}
509++ }
510++ data["disk_total"] = disk['total']
511++ data["disk_available"] = disk["free"]
512++ data["disk_used"] = data["disk_total"] - data["disk_available"]
513++ data["memory_mb"] = memory["total"]
514++ data["host_memory_total"] = memory["total"]
515++ data["host_memory_free"] = memory["free"]
516++ data['hypverisor_type'] = 'lxc'
517++ data['hypervisor_version'] = '1.0'
518++ data['hypervisor_hostname'] = platform.node()
519++ data['supported_instances'] = [('i686', 'lxc', 'lxc'),
520++ ('x86_64', 'lxc', 'lxc')]
521++ self._stats = data
522++ return data
523++
524++ def _get_host_memory(self):
525++ if sys.platform.upper() not in ['LINUX2', 'LINUX3']:
526++ return 1
527++
528++ data = {}
529++ for line in open('/proc/meminfo'):
530++ if ':' in line:
531++ key, value = line.split(":", 1)
532++ if key in ["MemTotal", "MemFree", "Buffers", "Cached"]:
533++ data[key] = int(value.split()[0])
534++ return{'total': data['MemTotal'],
535++ 'free': (data["MemFree"] +
536++ data["Buffers"] + data["Cached"])}
537++
538++ def _get_disk_info(self):
539++ hddinfo = os.statvfs(CONF.instances_path)
540++ total = hddinfo.f_frsize * hddinfo.f_blocks
541++ free = hddinfo.f_frsize * hddinfo.f_bavail
542++ return {'total': total, 'free': free}
543++
544++ def _get_cpu_info(self):
545++ cpuinfo = dict()
546++ cpuinfo['features'] = list()
547++ if sys.platform.upper() not in ['LINUX2', 'LINUX3']:
548++ return 0
549++
550++ f = open('/proc/cpuinfo', 'r')
551++ for line in f:
552++ if line.strip():
553++ if line.rstrip('\n').startswith('vendor_id'):
554++ cpuinfo['vendor'] = line.rstrip('\n').split(':')[1]
555++ if line.rstrip('\n').startswith('model_name'):
556++ cpuinfo['model'] = line.rstrip('\n').split(':')[1]
557++ if line.rstrip('\n').startswith('flags'):
558++ cpuinfo['features'] = line.rstrip('\n').split(':')[1]
559++
560++ cpuinfo['features'] = list(set(cpuinfo['features']))
561++ return cpuinfo
562+diff -Naurp nova/nova/virt/lxc/__init__.py nova.lxc/nova/virt/lxc/__init__.py
563+--- nova/nova/virt/lxc/__init__.py 1969-12-31 19:00:00.000000000 -0500
564++++ nova.lxc/nova/virt/lxc/__init__.py 2013-09-30 12:51:46.540449253 -0400
565+@@ -0,0 +1,22 @@
566++# vim: tabstop=4 shiftwidth=4 softtabstop=4
567++
568++# Copyright 2010 United States Government as represented by the
569++# Administrator of the National Aeronautics and Space Administration.
570++# All Rights Reserved.
571++# Copyright (c) 2013 Canonical Ltd
572++#
573++# Licensed under the Apache License, Version 2.0 (the "License"); you may
574++# not use this file except in compliance with the License. You may obtain
575++# a copy of the License at
576++#
577++# http://www.apache.org/licenses/LICENSE-2.0
578++#
579++# Unless required by applicable law or agreed to in writing, software
580++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
581++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
582++# License for the specific language governing permissions and limitations
583++# under the License.
584++
585++from nova.virt.lxc import driver
586++
587++LXCDriver = driver.LXCDriver
588+diff -Naurp nova/nova/virt/lxc/vmops.py nova.lxc/nova/virt/lxc/vmops.py
589+--- nova/nova/virt/lxc/vmops.py 1969-12-31 19:00:00.000000000 -0500
590++++ nova.lxc/nova/virt/lxc/vmops.py 2013-09-30 21:29:17.748464309 -0400
591+@@ -0,0 +1,146 @@
592++# vim: tabstop=4 shiftwidth=4 softtabstop=4
593++
594++# Copyright 2010 United States Government as represented by the
595++# Administrator of the National Aeronautics and Space Administration.
596++# All Rights Reserved.
597++# Copyright (c) 2013 Canonical Ltd
598++#
599++# Licensed under the Apache License, Version 2.0 (the "License"); you may
600++# not use this file except in compliance with the License. You may obtain
601++# a copy of the License at
602++#
603++# http://www.apache.org/licenses/LICENSE-2.0
604++#
605++# Unless required by applicable law or agreed to in writing, software
606++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
607++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
608++# License for the specific language governing permissions and limitations
609++# under the License.
610++
611++import os
612++
613++import jinja2
614++from oslo.config import cfg
615++
616++from nova.openstack.common.gettextutils import _
617++from nova.openstack.common import log as logging
618++from nova import utils
619++from nova.virt.disk import api as disk
620++from nova.virt import images
621++from nova.virt.libvirt import utils as libvirt_utils
622++from nova.virt.lxc import vmutils
623++
624++LOG = logging.getLogger(__name__)
625++
626++CONF = cfg.CONF
627++
628++MAX_CONSOLE_BYTES = 102400
629++
630++
631++class VMOps(object):
632++ def __init__(self):
633++ self.vmutils = vmutils.VMUtils()
634++
635++ def spawn(self, context, instance, image_meta, injected_files,
636++ admin_password, network_info=None, block_device_info=None):
637++ LOG.info(_('Spawning instance'))
638++ try:
639++ instance_path = os.path.join(CONF.instances_path,
640++ instance['uuid'])
641++ image_path = os.path.join(instance_path, 'disk')
642++ container_rootfs = os.path.join(instance_path, 'rootfs')
643++ lxc_container = os.path.join(CONF.lxc_path, instance['uuid'])
644++ console_file = os.path.join(instance_path, 'console.log')
645++
646++ def _lxc_setup_directories():
647++ LOG.info(_('Creating initial LXC directories'),
648++ instance=instance)
649++ if not os.path.exists(lxc_container):
650++ utils.execute('mkdir', '-p', lxc_container,
651++ run_as_root=True)
652++
653++ if not os.path.exists(container_rootfs):
654++ utils.execute('mkdir', '-p', container_rootfs,
655++ run_as_root=True)
656++
657++ if not os.path.exists(instance_path):
658++ os.mkdir(instance_path)
659++
660++ _lxc_setup_directories()
661++
662++ def _lxc_build_config():
663++ LOG.info(_('Build LXC configuration file'))
664++ for vif in network_info:
665++ mac_address = vif['address']
666++ network_bridge = network_info[0]['network']['bridge']
667++
668++ tmpl_path, tmpl_file = os.path.split(CONF.lxc_config_template)
669++ env = jinja2.Environment(
670++ loader=jinja2.FileSystemLoader(tmpl_path))
671++ template = env.get_template(tmpl_file)
672++ lxc_config = template.render(
673++ {'container_name': instance['uuid'],
674++ 'container_rootfs': container_rootfs,
675++ 'container_link': network_bridge,
676++ 'container_hwaddr': mac_address,
677++ 'console_file': console_file,
678++ 'container_fstab': '%s/%s/fstab'
679++ % (CONF.lxc_path, instance['uuid'])})
680++
681++ config_file = os.path.join(CONF.lxc_path, instance['uuid'],
682++ 'config')
683++ vmutils.write_to_file(config_file, lxc_config)
684++
685++ fstab_file = os.path.join(CONF.lxc_path, instance['uuid'],
686++ 'fstab')
687++ fstab_config = open(CONF.lxc_fstab_template, 'r').read()
688++ vmutils.write_to_file(fstab_file, fstab_config)
689++
690++ _lxc_build_config()
691++
692++ def _lxc_ready_container():
693++ LOG.info(_('Downloading and Mounting image'))
694++ images.fetch(context, instance['image_ref'], image_path,
695++ instance['user_id'], instance['project_id'])
696++ disk.setup_container(image_path,
697++ container_dir=container_rootfs,
698++ use_cow=CONF.use_cow_images)
699++
700++ _lxc_ready_container()
701++
702++ def _lxc_start_container():
703++ LOG.info(_('Starting LXC container'))
704++ self.vmutils.start_container(instance)
705++
706++ _lxc_start_container()
707++ except Exception as ex:
708++ LOG.exception(ex)
709++
710++ def destroy(self, instance, network_info, block_device_info=None,
711++ destroy_disks=True, context=None):
712++ LOG.info(_('Destroying LXC container'))
713++ container_dir = os.path.join(CONF.instances_path, instance['uuid'],
714++ 'rootfs')
715++ instance_dir = os.path.join(CONF.instances_path, instance['uuid'])
716++ disk.teardown_container(container_dir=container_dir)
717++ self.vmutils.destroy_container(instance)
718++
719++ def power_off(self, instance):
720++ self.vmutils.stop_container(instance)
721++
722++ def power_on(self, instance):
723++ self.vmutils.start_container(instance)
724++
725++ def get_console_output(self, instance):
726++ console_file = os.path.join(CONF.instances_path, instance['uuid'],
727++ 'console.log')
728++ with libvirt_utils.file_open(console_file, 'r') as fp:
729++ log_data, remaining = utils.last_bytes(fp,
730++ MAX_CONSOLE_BYTES)
731++ return log_data
732++
733++ def list_instances(self):
734++ return self.vmutils.list_containers()
735++
736++ def container_exists(self, instance):
737++ return self.vmutils.container_exists(instance)
738+diff -Naurp nova/nova/virt/lxc/vmutils.py nova.lxc/nova/virt/lxc/vmutils.py
739+--- nova/nova/virt/lxc/vmutils.py 1969-12-31 19:00:00.000000000 -0500
740++++ nova.lxc/nova/virt/lxc/vmutils.py 2013-09-30 21:30:28.124464343 -0400
741+@@ -0,0 +1,64 @@
742++# vim: tabstop=4 shiftwidth=4 softtabstop=4
743++
744++# Copyright 2010 United States Government as represented by the
745++# Administrator of the National Aeronautics and Space Administration.
746++# All Rights Reserved.
747++# Copyright (c) 2013 Canonical Ltd
748++#
749++# Licensed under the Apache License, Version 2.0 (the "License"); you may
750++# not use this file except in compliance with the License. You may obtain
751++# a copy of the License at
752++#
753++# http://www.apache.org/licenses/LICENSE-2.0
754++#
755++# Unless required by applicable law or agreed to in writing, software
756++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
757++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
758++# License for the specific language governing permissions and limitations
759++# under the License.
760++
761++
762++from nova.openstack.common.gettextutils import _ # noqa
763++from nova.openstack.common import log as logging
764++from nova import utils
765++
766++LOG = logging.getLogger(__name__)
767++
768++
769++def write_to_file(path, contents):
770++ utils.execute('tee', path,
771++ process_input=contents, run_as_root=True)
772++
773++
774++class VMUtils(object):
775++ def __init__(self):
776++ pass
777++
778++ def container_exists(self, instance):
779++ (state, out) = utils.execute('lxc-info', '--name', instance['uuid'],
780++ '-s', run_as_root=True)
781++ state = state.split()[1]
782++ if state == 'RUNNING':
783++ return True
784++ else:
785++ return False
786++
787++ def stop_container(self, instance):
788++ utils.execute('lxc-stop', '-n', instance['uuid'], run_as_root=True)
789++
790++ def start_container(self, instance):
791++ utils.execute('lxc-start', '-d', '--name', instance['uuid'],
792++ run_as_root=True)
793++
794++ def destroy_container(self, instance):
795++ utils.execute('lxc-destroy', '-f', '-n', instance['uuid'],
796++ run_as_root=True)
797++
798++ def find_container_pid(self, instance):
799++ (pid, err) = utils.execute('lxc-info', '-n', instance['uuid'], '-p',
800++ run_as_root=True)
801++ pid = pid.split()[1]
802++ return pid
803++
804++ def list_containers(self):
805++ utils.execute('lxc-ls', '-1', run_as_root=True)
806
807=== modified file 'debian/patches/series'
808--- debian/patches/series 2013-08-06 12:33:39 +0000
809+++ debian/patches/series 2013-10-02 17:10:37 +0000
810@@ -3,3 +3,4 @@
811 fix-docs-build-without-network.patch
812 fix-requirements.patch
813 avoid-failing-test.patch
814+native-lxc-hypervisor.patch

Subscribers

People subscribed via source and target branches