summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorjaypipes@gmail.com <>2010-10-27 10:51:37 -0400
committerjaypipes@gmail.com <>2010-10-27 10:51:37 -0400
commit24e19b43af5efe193bf28bed468e85ee57ce76df (patch)
tree76b9f1e5ed0453e10e2e2d1a4784afd56fd0b035 /nova/compute
parent198af0ef9e65bc4c2efe74b9d93cf40210eb77bc (diff)
parenteb82a8a7d8220adf31db3afb46849f24924ec973 (diff)
downloadnova-24e19b43af5efe193bf28bed468e85ee57ce76df.tar.gz
nova-24e19b43af5efe193bf28bed468e85ee57ce76df.tar.xz
nova-24e19b43af5efe193bf28bed468e85ee57ce76df.zip
Merge trunk and resolve conflicts
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/disk.py32
-rw-r--r--nova/compute/manager.py53
-rw-r--r--nova/compute/monitor.py111
-rw-r--r--nova/compute/power_state.py13
4 files changed, 118 insertions, 91 deletions
diff --git a/nova/compute/disk.py b/nova/compute/disk.py
index 447a29004..e362b4507 100644
--- a/nova/compute/disk.py
+++ b/nova/compute/disk.py
@@ -34,6 +34,8 @@ from nova import flags
FLAGS = flags.FLAGS
flags.DEFINE_integer('minimum_root_size', 1024 * 1024 * 1024 * 10,
'minimum size in bytes of root partition')
+flags.DEFINE_integer('block_size', 1024 * 1024 * 256,
+ 'block_size to use for dd')
@defer.inlineCallbacks
@@ -72,33 +74,36 @@ def partition(infile, outfile, local_bytes=0, resize=True,
" by sector size: %d / %d", local_bytes, sector_size)
local_sectors = local_bytes / sector_size
- mbr_last = 62 # a
- primary_first = mbr_last + 1 # b
- primary_last = primary_first + primary_sectors - 1 # c
- local_first = primary_last + 1 # d
- local_last = local_first + local_sectors - 1 # e
- last_sector = local_last # e
+ mbr_last = 62 # a
+ primary_first = mbr_last + 1 # b
+ primary_last = primary_first + primary_sectors - 1 # c
+ local_first = primary_last + 1 # d
+ local_last = local_first + local_sectors - 1 # e
+ last_sector = local_last # e
# create an empty file
yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
- % (outfile, last_sector, sector_size))
+ % (outfile, mbr_last, sector_size))
# make mbr partition
yield execute('parted --script %s mklabel msdos' % outfile)
+ # append primary file
+ yield execute('dd if=%s of=%s bs=%s conv=notrunc,fsync oflag=append'
+ % (infile, outfile, FLAGS.block_size))
+
# make primary partition
yield execute('parted --script %s mkpart primary %ds %ds'
% (outfile, primary_first, primary_last))
- # make local partition
if local_bytes > 0:
+ # make the file bigger
+ yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
+ % (outfile, last_sector, sector_size))
+ # make and format local partition
yield execute('parted --script %s mkpartfs primary %s %ds %ds'
% (outfile, local_type, local_first, local_last))
- # copy file into partition
- yield execute('dd if=%s of=%s bs=%d seek=%d conv=notrunc,fsync'
- % (infile, outfile, sector_size, primary_first))
-
@defer.inlineCallbacks
def inject_data(image, key=None, net=None, partition=None, execute=None):
@@ -157,7 +162,7 @@ def inject_data(image, key=None, net=None, partition=None, execute=None):
@defer.inlineCallbacks
def _inject_key_into_fs(key, fs, execute=None):
sshdir = os.path.join(os.path.join(fs, 'root'), '.ssh')
- yield execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter
+ yield execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter
yield execute('sudo chown root %s' % sshdir)
yield execute('sudo chmod 700 %s' % sshdir)
keyfile = os.path.join(sshdir, 'authorized_keys')
@@ -169,4 +174,3 @@ def _inject_net_into_fs(net, fs, execute=None):
netfile = os.path.join(os.path.join(os.path.join(
fs, 'etc'), 'network'), 'interfaces')
yield execute('sudo tee %s' % netfile, net)
-
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index c752d954b..d99d938af 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -20,10 +20,8 @@
Handles all code relating to instances (guest vms)
"""
-import base64
import datetime
import logging
-import os
from twisted.internet import defer
@@ -59,7 +57,11 @@ class ComputeManager(manager.Manager):
"""Update the state of an instance from the driver info"""
# FIXME(ja): include other fields from state?
instance_ref = self.db.instance_get(context, instance_id)
- state = self.driver.get_info(instance_ref.name)['state']
+ try:
+ info = self.driver.get_info(instance_ref['name'])
+ state = info['state']
+ except exception.NotFound:
+ state = power_state.NOSTATE
self.db.instance_set_state(context, instance_id, state)
@defer.inlineCallbacks
@@ -161,16 +163,15 @@ class ComputeManager(manager.Manager):
def reboot_instance(self, context, instance_id):
"""Reboot an instance on this server."""
context = context.elevated()
- self._update_state(context, instance_id)
instance_ref = self.db.instance_get(context, instance_id)
+ self._update_state(context, instance_id)
if instance_ref['state'] != power_state.RUNNING:
- raise exception.Error(
- 'trying to reboot a non-running'
- 'instance: %s (state: %s excepted: %s)' %
- (instance_ref['internal_id'],
- instance_ref['state'],
- power_state.RUNNING))
+ logging.warn('trying to reboot a non-running '
+ 'instance: %s (state: %s excepted: %s)',
+ instance_ref['internal_id'],
+ instance_ref['state'],
+ power_state.RUNNING)
logging.debug('instance %s: rebooting', instance_ref['name'])
self.db.instance_set_state(context,
@@ -180,6 +181,38 @@ class ComputeManager(manager.Manager):
yield self.driver.reboot(instance_ref)
self._update_state(context, instance_id)
+ @defer.inlineCallbacks
+ @exception.wrap_exception
+ def rescue_instance(self, context, instance_id):
+ """Rescue an instance on this server."""
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug('instance %s: rescuing',
+ instance_ref['internal_id'])
+ self.db.instance_set_state(context,
+ instance_id,
+ power_state.NOSTATE,
+ 'rescuing')
+ yield self.driver.rescue(instance_ref)
+ self._update_state(context, instance_id)
+
+ @defer.inlineCallbacks
+ @exception.wrap_exception
+ def unrescue_instance(self, context, instance_id):
+ """Rescue an instance on this server."""
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug('instance %s: unrescuing',
+ instance_ref['internal_id'])
+ self.db.instance_set_state(context,
+ instance_id,
+ power_state.NOSTATE,
+ 'unrescuing')
+ yield self.driver.unrescue(instance_ref)
+ self._update_state(context, instance_id)
+
@exception.wrap_exception
def get_console_output(self, context, instance_id):
"""Send the console output for an instance."""
diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py
index 268864900..d0154600f 100644
--- a/nova/compute/monitor.py
+++ b/nova/compute/monitor.py
@@ -85,8 +85,7 @@ RRD_VALUES = {
'RRA:MAX:0.5:6:800',
'RRA:MAX:0.5:24:800',
'RRA:MAX:0.5:444:800',
- ]
- }
+ ]}
utcnow = datetime.datetime.utcnow
@@ -97,15 +96,12 @@ def update_rrd(instance, name, data):
Updates the specified RRD file.
"""
filename = os.path.join(instance.get_rrd_path(), '%s.rrd' % name)
-
+
if not os.path.exists(filename):
init_rrd(instance, name)
-
+
timestamp = int(time.mktime(utcnow().timetuple()))
- rrdtool.update (
- filename,
- '%d:%s' % (timestamp, data)
- )
+ rrdtool.update(filename, '%d:%s' % (timestamp, data))
def init_rrd(instance, name):
@@ -113,29 +109,28 @@ def init_rrd(instance, name):
Initializes the specified RRD file.
"""
path = os.path.join(FLAGS.monitoring_rrd_path, instance.instance_id)
-
+
if not os.path.exists(path):
os.makedirs(path)
-
+
filename = os.path.join(path, '%s.rrd' % name)
-
+
if not os.path.exists(filename):
- rrdtool.create (
+ rrdtool.create(
filename,
'--step', '%d' % FLAGS.monitoring_instances_step,
'--start', '0',
- *RRD_VALUES[name]
- )
+ *RRD_VALUES[name])
+
-
def graph_cpu(instance, duration):
"""
Creates a graph of cpu usage for the specified instance and duration.
"""
path = instance.get_rrd_path()
filename = os.path.join(path, 'cpu-%s.png' % duration)
-
- rrdtool.graph (
+
+ rrdtool.graph(
filename,
'--disable-rrdtool-tag',
'--imgformat', 'PNG',
@@ -146,9 +141,8 @@ def graph_cpu(instance, duration):
'-l', '0',
'-u', '100',
'DEF:cpu=%s:cpu:AVERAGE' % os.path.join(path, 'cpu.rrd'),
- 'AREA:cpu#eacc00:% CPU',
- )
-
+ 'AREA:cpu#eacc00:% CPU',)
+
store_graph(instance.instance_id, filename)
@@ -158,8 +152,8 @@ def graph_net(instance, duration):
"""
path = instance.get_rrd_path()
filename = os.path.join(path, 'net-%s.png' % duration)
-
- rrdtool.graph (
+
+ rrdtool.graph(
filename,
'--disable-rrdtool-tag',
'--imgformat', 'PNG',
@@ -174,20 +168,19 @@ def graph_net(instance, duration):
'DEF:rx=%s:rx:AVERAGE' % os.path.join(path, 'net.rrd'),
'DEF:tx=%s:tx:AVERAGE' % os.path.join(path, 'net.rrd'),
'AREA:rx#00FF00:In traffic',
- 'LINE1:tx#0000FF:Out traffic',
- )
-
+ 'LINE1:tx#0000FF:Out traffic',)
+
store_graph(instance.instance_id, filename)
-
+
def graph_disk(instance, duration):
"""
Creates a graph of disk usage for the specified duration.
- """
+ """
path = instance.get_rrd_path()
filename = os.path.join(path, 'disk-%s.png' % duration)
-
- rrdtool.graph (
+
+ rrdtool.graph(
filename,
'--disable-rrdtool-tag',
'--imgformat', 'PNG',
@@ -202,9 +195,8 @@ def graph_disk(instance, duration):
'DEF:rd=%s:rd:AVERAGE' % os.path.join(path, 'disk.rrd'),
'DEF:wr=%s:wr:AVERAGE' % os.path.join(path, 'disk.rrd'),
'AREA:rd#00FF00:Read',
- 'LINE1:wr#0000FF:Write',
- )
-
+ 'LINE1:wr#0000FF:Write',)
+
store_graph(instance.instance_id, filename)
@@ -224,17 +216,16 @@ def store_graph(instance_id, filename):
is_secure=False,
calling_format=boto.s3.connection.OrdinaryCallingFormat(),
port=FLAGS.s3_port,
- host=FLAGS.s3_host
- )
+ host=FLAGS.s3_host)
bucket_name = '_%s.monitor' % instance_id
-
+
# Object store isn't creating the bucket like it should currently
# when it is first requested, so have to catch and create manually.
try:
bucket = s3.get_bucket(bucket_name)
except Exception:
bucket = s3.create_bucket(bucket_name)
-
+
key = boto.s3.Key(bucket)
key.key = os.path.basename(filename)
key.set_contents_from_filename(filename)
@@ -247,18 +238,18 @@ class Instance(object):
self.last_updated = datetime.datetime.min
self.cputime = 0
self.cputime_last_updated = None
-
+
init_rrd(self, 'cpu')
init_rrd(self, 'net')
init_rrd(self, 'disk')
-
+
def needs_update(self):
"""
Indicates whether this instance is due to have its statistics updated.
"""
delta = utcnow() - self.last_updated
return delta.seconds >= FLAGS.monitoring_instances_step
-
+
def update(self):
"""
Updates the instances statistics and stores the resulting graphs
@@ -271,7 +262,7 @@ class Instance(object):
if data != None:
logging.debug('CPU: %s', data)
update_rrd(self, 'cpu', data)
-
+
data = self.fetch_net_stats()
logging.debug('NET: %s', data)
update_rrd(self, 'net', data)
@@ -279,7 +270,7 @@ class Instance(object):
data = self.fetch_disk_stats()
logging.debug('DISK: %s', data)
update_rrd(self, 'disk', data)
-
+
# TODO(devcamcar): Turn these into pool.ProcessPool.execute() calls
# and make the methods @defer.inlineCallbacks.
graph_cpu(self, '1d')
@@ -297,13 +288,13 @@ class Instance(object):
logging.exception('unexpected error during update')
self.last_updated = utcnow()
-
+
def get_rrd_path(self):
"""
Returns the path to where RRD files are stored.
"""
return os.path.join(FLAGS.monitoring_rrd_path, self.instance_id)
-
+
def fetch_cpu_stats(self):
"""
Returns cpu usage statistics for this instance.
@@ -327,17 +318,17 @@ class Instance(object):
# Calculate the number of seconds between samples.
d = self.cputime_last_updated - cputime_last_updated
t = d.days * 86400 + d.seconds
-
+
logging.debug('t = %d', t)
# Calculate change over time in number of nanoseconds of CPU time used.
cputime_delta = self.cputime - cputime_last
-
+
logging.debug('cputime_delta = %s', cputime_delta)
# Get the number of virtual cpus in this domain.
vcpus = int(info['num_cpu'])
-
+
logging.debug('vcpus = %d', vcpus)
# Calculate CPU % used and cap at 100.
@@ -349,9 +340,9 @@ class Instance(object):
"""
rd = 0
wr = 0
-
+
disks = self.conn.get_disks(self.instance_id)
-
+
# Aggregate the read and write totals.
for disk in disks:
try:
@@ -363,7 +354,7 @@ class Instance(object):
logging.error('Cannot get blockstats for "%s" on "%s"',
disk, self.instance_id)
raise
-
+
return '%d:%d' % (rd, wr)
def fetch_net_stats(self):
@@ -372,9 +363,9 @@ class Instance(object):
"""
rx = 0
tx = 0
-
+
interfaces = self.conn.get_interfaces(self.instance_id)
-
+
# Aggregate the in and out totals.
for interface in interfaces:
try:
@@ -385,7 +376,7 @@ class Instance(object):
logging.error('Cannot get ifstats for "%s" on "%s"',
interface, self.instance_id)
raise
-
+
return '%d:%d' % (rx, tx)
@@ -400,16 +391,16 @@ class InstanceMonitor(object, service.Service):
"""
self._instances = {}
self._loop = task.LoopingCall(self.updateInstances)
-
+
def startService(self):
self._instances = {}
self._loop.start(interval=FLAGS.monitoring_instances_delay)
service.Service.startService(self)
-
+
def stopService(self):
self._loop.stop()
service.Service.stopService(self)
-
+
def updateInstances(self):
"""
Update resource usage for all running instances.
@@ -420,20 +411,20 @@ class InstanceMonitor(object, service.Service):
logging.exception('unexpected exception getting connection')
time.sleep(FLAGS.monitoring_instances_delay)
return
-
+
domain_ids = conn.list_instances()
try:
- self.updateInstances_(conn, domain_ids)
+ self.updateInstances_(conn, domain_ids)
except Exception, exn:
- logging.exception('updateInstances_')
+ logging.exception('updateInstances_')
def updateInstances_(self, conn, domain_ids):
for domain_id in domain_ids:
- if not domain_id in self._instances:
+ if not domain_id in self._instances:
instance = Instance(conn, domain_id)
self._instances[domain_id] = instance
logging.debug('Found instance: %s', domain_id)
-
+
for key in self._instances.keys():
instance = self._instances[key]
if instance.needs_update():
diff --git a/nova/compute/power_state.py b/nova/compute/power_state.py
index b27aa4677..cefdf2d9e 100644
--- a/nova/compute/power_state.py
+++ b/nova/compute/power_state.py
@@ -30,12 +30,11 @@ CRASHED = 0x06
def name(code):
d = {
- NOSTATE : 'pending',
- RUNNING : 'running',
- BLOCKED : 'blocked',
- PAUSED : 'paused',
+ NOSTATE: 'pending',
+ RUNNING: 'running',
+ BLOCKED: 'blocked',
+ PAUSED: 'paused',
SHUTDOWN: 'shutdown',
- SHUTOFF : 'shutdown',
- CRASHED : 'crashed',
- }
+ SHUTOFF: 'shutdown',
+ CRASHED: 'crashed'}
return d[code]