diff options
| author | jaypipes@gmail.com <> | 2010-10-27 10:51:37 -0400 |
|---|---|---|
| committer | jaypipes@gmail.com <> | 2010-10-27 10:51:37 -0400 |
| commit | 24e19b43af5efe193bf28bed468e85ee57ce76df (patch) | |
| tree | 76b9f1e5ed0453e10e2e2d1a4784afd56fd0b035 /nova/compute | |
| parent | 198af0ef9e65bc4c2efe74b9d93cf40210eb77bc (diff) | |
| parent | eb82a8a7d8220adf31db3afb46849f24924ec973 (diff) | |
| download | nova-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.py | 32 | ||||
| -rw-r--r-- | nova/compute/manager.py | 53 | ||||
| -rw-r--r-- | nova/compute/monitor.py | 111 | ||||
| -rw-r--r-- | nova/compute/power_state.py | 13 |
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] |
