From fec64824a1f2820da172e45b4a6e4ef14fca4841 Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Sun, 4 May 2014 21:05:15 +0000 Subject: [PATCH 1/7] Revert changes in fake.py --- nova/virt/fake.py | 56 ++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/nova/virt/fake.py b/nova/virt/fake.py index c17c35a47f6..41825a94f2a 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -24,6 +24,7 @@ semantics of real hypervisor connections. """ + from oslo.config import cfg from nova import block_device @@ -45,19 +46,6 @@ _FAKE_NODES = None -host_resource = {'vcpus': 1, - 'memory_mb': 1024, - 'memory_mb_used' : 0, - 'local_gb': 1028, - 'vcpus_used': 0, - 'memory_mb_used': 0, - 'local_gb_used': 0, - 'hypervisor_type': 'fake', - 'hypervisor_version': '1.0', - 'hypervisor_hostname': CONF.host, - 'disk_available_least': 0, - 'cpu_info': '?'} - def set_nodes(nodes): """Sets FakeDriver's node.list. @@ -103,30 +91,22 @@ def __init__(self, virtapi, read_only=False): super(FakeDriver, self).__init__(virtapi) self.instances = {} self.host_status_base = { - 'vcpus': 2, - 'memory_mb': 582, - 'local_gb': 6000, + 'vcpus': 100000, + 'memory_mb': 8000000000, + 'local_gb': 600000000000, 'vcpus_used': 0, 'memory_mb_used': 0, - 'local_gb_used': 0, + 'local_gb_used': 100000000000, 'hypervisor_type': 'fake', 'hypervisor_version': '1.0', 'hypervisor_hostname': CONF.host, 'cpu_info': {}, - 'disk_available_least': 5000, + 'disk_available_least': 500000000000, } - self._mounts = {} self._interfaces = {} if not _FAKE_NODES: - nodes = [] - for i in xrange(CONF.compute_processes): - if i == 0: - nodes.append(CONF.host) - else: - nodes.append('%s-%s' % (CONF.host, str(i))) - - set_nodes(nodes) + set_nodes([CONF.host]) def init_host(self, host): return @@ -362,16 +342,18 @@ def get_available_resource(self, nodename): if nodename not in _FAKE_NODES: return {} - host_resource['hypervisor_hostname'] = nodename - - host = self.fake_get_host_resource() - - return host - - - def fake_get_host_resource(self): - """Any calculation of host resource cost in simulator project in the future shoule be added here""" - return host_resource + dic = {'vcpus': 1, + 'memory_mb': 8192, + 'local_gb': 1028, + 'vcpus_used': 0, + 'memory_mb_used': 0, + 'local_gb_used': 0, + 'hypervisor_type': 'fake', + 'hypervisor_version': '1.0', + 'hypervisor_hostname': nodename, + 'disk_available_least': 0, + 'cpu_info': '?'} + return dic def ensure_filtering_rules_for_instance(self, instance_ref, network_info): return From 3ed8d671414645a72bcd40a38859785bf09a06e6 Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 06:09:48 +0000 Subject: [PATCH 2/7] Add SimulatorDriver with method patching to simulate delays and errors --- nova/virt/driver.py | 5 ++- nova/virt/simulator.py | 87 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 nova/virt/simulator.py diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 973b9037f53..708ed2ea377 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -36,8 +36,9 @@ cfg.StrOpt('compute_driver', help='Driver to use for controlling virtualization. Options ' 'include: libvirt.LibvirtDriver, xenapi.XenAPIDriver, ' - 'fake.FakeDriver, baremetal.BareMetalDriver, ' - 'vmwareapi.VMwareESXDriver, vmwareapi.VMwareVCDriver'), + 'fake.FakeDriver, simulator.SimulatorDriver, ' + 'baremetal.BareMetalDriver, vmwareapi.VMwareESXDriver, ' + 'vmwareapi.VMwareVCDriver'), cfg.StrOpt('default_ephemeral_format', help='The default format an ephemeral_volume will be ' 'formatted with on creation.'), diff --git a/nova/virt/simulator.py b/nova/virt/simulator.py new file mode 100644 index 00000000000..8d0875a2b73 --- /dev/null +++ b/nova/virt/simulator.py @@ -0,0 +1,87 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# 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. + +""" +:mod:`simulator` -- Fake driver that simulates errors and cluster capacity +=========================================================================== +""" + +import logging +import random +import time + +import fake +from nova import exception +from oslo.config import cfg + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + +simulator_opts = [ + cfg.FloatOpt('simulator_delay_probability', + default=0.5, + help='Delay a request issued to the SimulatorDriver with the' + 'specified probability'), + cfg.IntOpt('simulator_delay_ms', + default=0, + help='Delay a request by the specified number of milliseconds'), + cfg.FloatOpt('simulator_error_probability', + default=0.5, + help='Inject a NovaException to the SimulatorDriver with the' + 'specified probability'), + ] + +CONF.register_opts(simulator_opts) + +CONF = cfg.CONF +CONF.import_opt('host', 'nova.netconf') +CONF.import_opt('simulator_error_probability', 'nova.virt.simulator') +CONF.import_opt('simulator_delay_probability', 'nova.virt.simulator') +CONF.import_opt('simulator_delay_ms', 'nova.virt.simulator') + +to_simulate = ['spawn', 'live_snapshot', 'snapshot', 'reboot', + 'resume_state_on_host_boot', 'rescue', 'unrescue', + 'migrate_disk_and_power_off', 'finish_revert_migration', + 'power_off', 'power_on', 'soft_delete', 'restore', + 'pause', 'unpause', 'suspend', 'resume', 'destroy', + 'swap_volume', 'finish_migration', 'finish_migration'] + + +def inject(p): + return random.random() < p + + +def simulate(method): + if method.__name__ not in to_simulate: + return method + + if inject(CONF.simulator_delay_probability): + delay_duration = random.random() * CONF.simulator_delay_ms / 1000.0 + LOG.debug("Simulator injecting delay of %s ms" % delay_duration) + time.sleep(delay_duration) + + if inject(CONF.simulator_error_probability): + LOG.debug("Simulator injecting NovaException") + raise exception.NovaException + + return method + + +class SimulatorDriver(fake.FakeDriver): + def __init__(self, virtapi, read_only=False): + super(SimulatorDriver, self).__init__(virtapi, read_only) + + def __getattribute__(self, *args): + f = super(SimulatorDriver, self).__getattribute__(*args) + return simulate(f) From 636c677833ec7043aad16332f7c6fb254977ecb9 Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 06:29:47 +0000 Subject: [PATCH 3/7] Add resource configurability --- nova/virt/simulator.py | 58 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/nova/virt/simulator.py b/nova/virt/simulator.py index 8d0875a2b73..b8054c1fa4b 100644 --- a/nova/virt/simulator.py +++ b/nova/virt/simulator.py @@ -1,5 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 # # 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 @@ -30,14 +29,14 @@ simulator_opts = [ cfg.FloatOpt('simulator_delay_probability', - default=0.5, + default=0.0, help='Delay a request issued to the SimulatorDriver with the' 'specified probability'), cfg.IntOpt('simulator_delay_ms', default=0, help='Delay a request by the specified number of milliseconds'), cfg.FloatOpt('simulator_error_probability', - default=0.5, + default=0.0, help='Inject a NovaException to the SimulatorDriver with the' 'specified probability'), ] @@ -63,7 +62,7 @@ def inject(p): def simulate(method): - if method.__name__ not in to_simulate: + if callable(method) and method.__name__ not in to_simulate: return method if inject(CONF.simulator_delay_probability): @@ -82,6 +81,55 @@ class SimulatorDriver(fake.FakeDriver): def __init__(self, virtapi, read_only=False): super(SimulatorDriver, self).__init__(virtapi, read_only) + nodes = [] + nodes.append(CONF.host) + fake.set_nodes(nodes) + self.host_status_base = { + 'vcpus': 2, + 'memory_mb': 512, + 'local_gb': 6000, + 'vcpus_used': 0, + 'memory_mb_used': 0, + 'local_gb_used': 0, + 'hypervisor_type': 'fake', + 'hypervisor_version': '1.0', + 'hypervisor_hostname': CONF.host, + 'cpu_info': {}, + 'disk_available_least': 5000, + } + self.host_resource = { + 'vcpus': 1, + 'memory_mb': 1024, + 'memory_mb_used': 0, + 'local_gb': 1028, + 'vcpus_used': 0, + 'memory_mb_used': 0, + 'local_gb_used': 0, + 'hypervisor_type': 'fake', + 'hypervisor_version': '1.0', + 'hypervisor_hostname': CONF.host, + 'disk_available_least': 0, + 'cpu_info': '?' + } + + def get_available_resource(self, nodename): + """Updates compute manager resource info on ComputeNode table. + + Since we don't have a real hypervisor, pretend we have lots of + disk and ram. + """ + if nodename not in fake._FAKE_NODES: + return {} + + host = self.fake_get_host_resource() + + return host + + def fake_get_host_resource(self): + """Any calculation of host resource cost in simulator project " + in the future shoule be added here""" + return self.host_resource + def __getattribute__(self, *args): f = super(SimulatorDriver, self).__getattribute__(*args) return simulate(f) From 0989914f8d39b65cabf31c9b6a278bdb0959a420 Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 06:32:46 +0000 Subject: [PATCH 4/7] Update sample conf file with simulator options --- nova-simulator.conf.sample | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nova-simulator.conf.sample b/nova-simulator.conf.sample index becc94716f6..bbff0f8fdcb 100644 --- a/nova-simulator.conf.sample +++ b/nova-simulator.conf.sample @@ -17,7 +17,10 @@ quota_floating_ips = -1 quota_ram = -1 quota_cores = -1 quota_instances = -1 -compute_driver = nova.virt.fake.FakeDriver +compute_driver = nova.virt.fake.SimulatorDriver +simulator_delay_probability = 0.0 +simulator_delay_ms = 0 +simulator_error_probability = 0.0 compute_processes = 3 glance_api_servers = 10.0.2.15:9292 rabbit_password = password From 198938061eb22abcd5159148b9ba4cc6802064ca Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 06:39:22 +0000 Subject: [PATCH 5/7] Revert changes to service --- nova/service.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nova/service.py b/nova/service.py index ec2b1f3b184..60bd6403d6d 100644 --- a/nova/service.py +++ b/nova/service.py @@ -383,14 +383,16 @@ def process_launcher(): # NOTE(vish): the global launcher is to maintain the existing # functionality of calling service.serve + # service.wait -_launcher = [] +_launcher = None def serve(server, workers=None): global _launcher - _launcher.append(service.launch(server, workers=workers)) + if _launcher: + raise RuntimeError(_('serve() can only be called once')) + + _launcher = service.launch(server, workers=workers) def wait(): - for service in _launcher: - service.wait() + _launcher.wait() From d341892f09fb0dfa31fcd57ef8000b17bc641d4b Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 06:45:03 +0000 Subject: [PATCH 6/7] Revert changes to nova compute --- nova/cmd/compute.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/nova/cmd/compute.py b/nova/cmd/compute.py index 169b753c76a..f03a9bd6531 100644 --- a/nova/cmd/compute.py +++ b/nova/cmd/compute.py @@ -34,9 +34,7 @@ from nova import utils CONF = cfg.CONF -CONF.import_opt('host', 'nova.netconf') CONF.import_opt('compute_topic', 'nova.compute.rpcapi') -CONF.import_opt('compute_processes', 'nova.compute.simulator') CONF.import_opt('use_local', 'nova.conductor.api', group='conductor') @@ -65,15 +63,8 @@ def main(): objects_base.NovaObject.indirection_api = \ conductor_rpcapi.ConductorAPI() - for i in xrange(CONF.compute_processes): - if i > 0: - host = '%s-%s' % (CONF.host, str(i)) - else: - host = CONF.host - - server = service.Service.create(binary='nova-compute', - topic=CONF.compute_topic, - host=host, - db_allowed=False) - service.serve(server) + server = service.Service.create(binary='nova-compute', + topic=CONF.compute_topic, + db_allowed=False) + service.serve(server) service.wait() From 2eae66d9cb0bab15e2003054e23dab5a0856e774 Mon Sep 17 00:00:00 2001 From: Alvaro Morales Date: Mon, 5 May 2014 07:48:04 +0000 Subject: [PATCH 7/7] Fix path to SimulatorDriver in sample conf file --- nova-simulator.conf.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova-simulator.conf.sample b/nova-simulator.conf.sample index bbff0f8fdcb..5811d6af40d 100644 --- a/nova-simulator.conf.sample +++ b/nova-simulator.conf.sample @@ -17,7 +17,7 @@ quota_floating_ips = -1 quota_ram = -1 quota_cores = -1 quota_instances = -1 -compute_driver = nova.virt.fake.SimulatorDriver +compute_driver = nova.virt.simulator.SimulatorDriver simulator_delay_probability = 0.0 simulator_delay_ms = 0 simulator_error_probability = 0.0