Merge patch 30001

This commit is contained in:
Vishvananda Ishaya
2010-07-02 10:31:44 -05:00
2 changed files with 62 additions and 41 deletions
+13 -4
View File
@@ -38,10 +38,7 @@ class StorageTestCase(test.TrialTestCase):
self.mystorage = None
self.flags(fake_libvirt=True,
fake_storage=True)
if FLAGS.fake_storage:
self.mystorage = storage.FakeBlockStore()
else:
self.mystorage = storage.BlockStore()
self.mystorage = storage.BlockStore()
def test_run_create_volume(self):
vol_size = '0'
@@ -65,6 +62,18 @@ class StorageTestCase(test.TrialTestCase):
self.mystorage.create_volume,
vol_size, user_id, project_id)
def test_too_many_volumes(self):
vol_size = '1'
user_id = 'fake'
project_id = 'fake'
num_shelves = FLAGS.last_shelf_id - FLAGS.first_shelf_id + 1
total_slots = FLAGS.slots_per_shelf * num_shelves
for i in xrange(total_slots):
self.mystorage.create_volume(vol_size, user_id, project_id)
self.assertRaises(storage.NoMoreVolumes,
self.mystorage.create_volume,
vol_size, user_id, project_id)
def test_run_attach_detach_volume(self):
# Create one volume and one node to test with
instance_id = "storage-test"
+49 -37
View File
@@ -26,9 +26,10 @@ Currently uses Ata-over-Ethernet.
import glob
import logging
import random
import os
import socket
import subprocess
import shutil
import tempfile
import time
from nova import vendor
@@ -38,7 +39,6 @@ from twisted.internet import defer
from nova import datastore
from nova import exception
from nova import flags
from nova import rpc
from nova import utils
from nova import validate
@@ -53,16 +53,27 @@ flags.DEFINE_string('aoe_eth_dev', 'eth0',
flags.DEFINE_string('storage_name',
socket.gethostname(),
'name of this node')
flags.DEFINE_integer('shelf_id',
utils.last_octet(utils.get_my_ip()),
'AoE shelf_id for this node')
flags.DEFINE_integer('first_shelf_id',
utils.last_octet(utils.get_my_ip()) * 10,
'AoE starting shelf_id for this node')
flags.DEFINE_integer('last_shelf_id',
utils.last_octet(utils.get_my_ip()) * 10 + 9,
'AoE starting shelf_id for this node')
flags.DEFINE_string('aoe_export_dir',
'/var/lib/vblade-persist/vblades',
'AoE directory where exports are created')
flags.DEFINE_integer('slots_per_shelf',
16,
'Number of AoE slots per shelf')
flags.DEFINE_string('storage_availability_zone',
'nova',
'availability zone of this node')
flags.DEFINE_boolean('fake_storage', False,
'Should we make real storage volumes to attach?')
# TODO(joshua) Index of volumes by project
class NoMoreVolumes(exception.Error):
pass
def get_volume(volume_id):
""" Returns a redis-backed volume object """
@@ -83,9 +94,14 @@ class BlockStore(object):
super(BlockStore, self).__init__()
self.volume_class = Volume
if FLAGS.fake_storage:
FLAGS.aoe_export_dir = tempfile.mkdtemp()
self.volume_class = FakeVolume
self._init_volume_group()
def __del__(self):
if FLAGS.fake_storage:
shutil.rmtree(FLAGS.aoe_export_dir)
def report_state(self):
#TODO: aggregate the state of the system
pass
@@ -139,20 +155,8 @@ class BlockStore(object):
utils.runthis("PVCreate returned: %s", "sudo pvcreate %s" % (FLAGS.storage_dev))
utils.runthis("VGCreate returned: %s", "sudo vgcreate %s %s" % (FLAGS.volume_group, FLAGS.storage_dev))
class FakeBlockStore(BlockStore):
def __init__(self):
super(FakeBlockStore, self).__init__()
def _init_volume_group(self):
pass
def _restart_exports(self):
pass
class Volume(datastore.RedisModel):
# TODO(joshua) Index of volumes by project
object_type = 'volume'
def __init__(self, volume_id=None):
@@ -177,7 +181,7 @@ class Volume(datastore.RedisModel):
vol['delete_on_termination'] = 'False'
vol.save()
vol.create_lv()
vol.setup_export()
vol._setup_export()
# TODO(joshua) - We need to trigger a fanout message for aoe-discover on all the nodes
# TODO(joshua
vol['status'] = "available"
@@ -229,15 +233,22 @@ class Volume(datastore.RedisModel):
def _delete_lv(self):
utils.runthis("Removing LV: %s", "sudo lvremove -f %s/%s" % (FLAGS.volume_group, self['volume_id']))
def setup_export(self):
def _setup_export(self):
(shelf_id, blade_id) = get_next_aoe_numbers()
self['aoe_device'] = "e%s.%s" % (shelf_id, blade_id)
self['shelf_id'] = shelf_id
self['blade_id'] = blade_id
self.save()
self._exec_export()
def _exec_export(self):
utils.runthis("Creating AOE export: %s",
"sudo vblade-persist setup %s %s %s /dev/%s/%s" %
(shelf_id, blade_id, FLAGS.aoe_eth_dev, FLAGS.volume_group, self['volume_id']))
"sudo vblade- persist setup %s %s %s /dev/%s/%s" %
(self['shelf_id'],
self['blade_id'],
FLAGS.aoe_eth_dev,
FLAGS.volume_group,
self['volume_id']))
def _remove_export(self):
utils.runthis("Stopped AOE export: %s", "sudo vblade-persist stop %s %s" % (self['shelf_id'], self['blade_id']))
@@ -248,13 +259,10 @@ class FakeVolume(Volume):
def create_lv(self):
pass
def setup_export(self):
# TODO(???): This may not be good enough?
blade_id = ''.join([random.choice('0123456789') for x in xrange(3)])
self['shelf_id'] = FLAGS.shelf_id
self['blade_id'] = blade_id
self['aoe_device'] = "e%s.%s" % (FLAGS.shelf_id, blade_id)
self.save()
def _exec_export(self):
fname = os.path.join(FLAGS.aoe_export_dir, self['aoe_device'])
f = file(fname, "w")
f.close()
def _remove_export(self):
pass
@@ -263,9 +271,13 @@ class FakeVolume(Volume):
pass
def get_next_aoe_numbers():
aoes = glob.glob("/var/lib/vblade-persist/vblades/e*")
aoes.extend(['e0.0'])
blade_id = int(max([int(a.split('.')[1]) for a in aoes])) + 1
logging.debug("Next blade_id is %s" % (blade_id))
shelf_id = FLAGS.shelf_id
return (shelf_id, blade_id)
for shelf_id in xrange(FLAGS.first_shelf_id, FLAGS.last_shelf_id + 1):
aoes = glob.glob("%s/e%s.*" % (FLAGS.aoe_export_dir, shelf_id))
if not aoes:
blade_id = 0
else:
blade_id = int(max([int(a.rpartition('.')[2]) for a in aoes])) + 1
if blade_id < FLAGS.slots_per_shelf:
logging.debug("Next shelf.blade is %s.%s", shelf_id, blade_id)
return (shelf_id, blade_id)
raise NoMoreVolumes()