Convert to UNIX line endings

Fixes bug #972660

Change-Id: Iffe099504ae847ab2435e867860ab6bac6ca8252
diff --git a/stress/__init__.py b/stress/__init__.py
index 256d40e..0875e0b 100644
--- a/stress/__init__.py
+++ b/stress/__init__.py
@@ -1,17 +1,17 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""Basic framework for constructing various simulated workloads for a

-nova cluster."""

-

-__author__ = "David Kranz and Eugene Shih"

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""Basic framework for constructing various simulated workloads for a
+nova cluster."""
+
+__author__ = "David Kranz and Eugene Shih"
diff --git a/stress/basher.py b/stress/basher.py
index b6fcfca..e34738f 100644
--- a/stress/basher.py
+++ b/stress/basher.py
@@ -1,41 +1,41 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""Class to describe actions to be included in a stress test."""

-

-

-class BasherAction(object):

-    """

-    Used to describe each action that you would like to include in a test run.

-    """

-

-    def __init__(self, test_case, probability, pargs=[], kargs={}):

-        """

-        `test_case`  : the name of the class that implements the action

-        `pargs`      : positional arguments to the constructor of `test_case`

-        `kargs`      : keyword arguments to the constructor of `test_case`

-        `probability`: frequency that each action

-        """

-        self.test_case = test_case

-        self.pargs = pargs

-        self.kargs = kargs

-        self.probability = probability

-

-    def invoke(self, manager, state):

-        """

-        Calls the `run` method of the `test_case`.

-        """

-        return self.test_case.run(manager, state, *self.pargs, **self.kargs)

-

-    def __str__(self):

-        return self.test_case.__class__.__name__

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""Class to describe actions to be included in a stress test."""
+
+
+class BasherAction(object):
+    """
+    Used to describe each action that you would like to include in a test run.
+    """
+
+    def __init__(self, test_case, probability, pargs=[], kargs={}):
+        """
+        `test_case`  : the name of the class that implements the action
+        `pargs`      : positional arguments to the constructor of `test_case`
+        `kargs`      : keyword arguments to the constructor of `test_case`
+        `probability`: frequency that each action
+        """
+        self.test_case = test_case
+        self.pargs = pargs
+        self.kargs = kargs
+        self.probability = probability
+
+    def invoke(self, manager, state):
+        """
+        Calls the `run` method of the `test_case`.
+        """
+        return self.test_case.run(manager, state, *self.pargs, **self.kargs)
+
+    def __str__(self):
+        return self.test_case.__class__.__name__
diff --git a/stress/config.py b/stress/config.py
index 16972d8..64091cd 100755
--- a/stress/config.py
+++ b/stress/config.py
@@ -1,53 +1,53 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-

-import ConfigParser

-

-

-class StressConfig(object):

-    """Provides configuration information for whitebox stress tests."""

-

-    def __init__(self, conf):

-        self.conf = conf

-

-    def get(self, item_name, default_value=None):

-        try:

-            return self.conf.get("stress", item_name)

-        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):

-            return default_value

-

-    @property

-    def host_private_key_path(self):

-        """Path to ssh key for logging into compute nodes."""

-        return self.get("host_private_key_path", None)

-

-    @property

-    def host_admin_user(self):

-        """Username for logging into compute nodes."""

-        return self.get("host_admin_user", None)

-

-    @property

-    def nova_logdir(self):

-        """Directory containing log files on the compute nodes"""

-        return self.get("nova_logdir", None)

-

-    @property

-    def controller(self):

-        """Controller host"""

-        return self.get("controller", None)

-

-    @property

-    def max_instances(self):

-        """Maximum number of instances to create during test"""

-        return self.get("max_instances", 16)

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+
+import ConfigParser
+
+
+class StressConfig(object):
+    """Provides configuration information for whitebox stress tests."""
+
+    def __init__(self, conf):
+        self.conf = conf
+
+    def get(self, item_name, default_value=None):
+        try:
+            return self.conf.get("stress", item_name)
+        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
+            return default_value
+
+    @property
+    def host_private_key_path(self):
+        """Path to ssh key for logging into compute nodes."""
+        return self.get("host_private_key_path", None)
+
+    @property
+    def host_admin_user(self):
+        """Username for logging into compute nodes."""
+        return self.get("host_admin_user", None)
+
+    @property
+    def nova_logdir(self):
+        """Directory containing log files on the compute nodes"""
+        return self.get("nova_logdir", None)
+
+    @property
+    def controller(self):
+        """Controller host"""
+        return self.get("controller", None)
+
+    @property
+    def max_instances(self):
+        """Maximum number of instances to create during test"""
+        return self.get("max_instances", 16)
diff --git a/stress/driver.py b/stress/driver.py
index e8c8f12..9f263f6 100644
--- a/stress/driver.py
+++ b/stress/driver.py
@@ -1,207 +1,207 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""The entry point for the execution of a workloadTo execute a workload.

-Users pass in a description of the workload and a nova manager object

-to the bash_openstack function call"""

-

-

-import random

-import datetime

-import time

-

-

-# local imports

-from test_case import *

-from state import State

-import utils.util

-from config import StressConfig

-

-# setup logging to file

-logging.basicConfig(

-    format='%(asctime)s %(name)-20s %(levelname)-8s %(message)s',

-    datefmt='%m-%d %H:%M:%S',

-    filename="stress.debug.log",

-    filemode="w",

-    level=logging.DEBUG,

-    )

-

-# define a Handler which writes INFO messages or higher to the sys.stdout

-_console = logging.StreamHandler()

-_console.setLevel(logging.INFO)

-# set a format which is simpler for console use

-_formatter = logging.Formatter('%(name)-20s: %(levelname)-8s %(message)s')

-# tell the handler to use this format

-_console.setFormatter(_formatter)

-# add the handler to the root logger

-logging.getLogger('').addHandler(_console)

-

-

-def _create_cases(choice_spec):

-    """

-    Generate a workload of tests from workload description

-    """

-    cases = []

-    count = 0

-    for choice in choice_spec:

-        p = choice.probability

-        for i in range(p):

-            cases.append(choice)

-        i = i + p

-        count = count + p

-    assert(count == 100)

-    return cases

-

-

-def _get_compute_nodes(keypath, user, controller):

-    """

-    Returns a list of active compute nodes. List is generated by running

-    nova-manage on the controller.

-    """

-    nodes = []

-    if keypath == None or user == None:

-        return nodes

-    lines = utils.util.ssh(keypath, user, controller,

-                     "nova-manage service list | grep ^nova-compute").\

-                     split('\n')

-    # For example: nova-compute xg11eth0 nova enabled :-) 2011-10-31 18:57:46

-    # This is fragile but there is, at present, no other way to get this info.

-    for line in lines:

-        words = line.split()

-        if len(words) > 0 and words[4] == ":-)":

-            nodes.append(words[1])

-    return nodes

-

-

-def _error_in_logs(keypath, logdir, user, nodes):

-    """

-    Detect errors in the nova log files on the controller and compute nodes.

-    """

-    grep = 'egrep "ERROR\|TRACE" %s/*.log' % logdir

-    for node in nodes:

-        errors = utils.util.ssh(keypath, user, node, grep, check=False)

-        if len(errors) > 0:

-            logging.error('%s: %s' % (node, errors))

-            return True

-    return False

-

-

-def bash_openstack(manager,

-                   choice_spec,

-                   **kwargs):

-    """

-    Workload driver. Executes a workload as specified by the `choice_spec`

-    parameter against a nova-cluster.

-

-    `manager`  : Manager object

-    `choice_spec` : list of BasherChoice actions to run on the cluster

-    `kargs`       : keyword arguments to the constructor of `test_case`

-                    `duration`   = how long this test should last (3 sec)

-                    `sleep_time` = time to sleep between actions (in msec)

-                    `test_name`  = human readable workload description

-                                   (default: unnamed test)

-                    `max_vms`    = maximum number of instances to launch

-                                   (default: 32)

-                    `seed`       = random seed (default: None)

-    """

-    stress_config = StressConfig(manager.config._conf)

-    # get keyword arguments

-    duration = kwargs.get('duration', datetime.timedelta(seconds=10))

-    seed = kwargs.get('seed', None)

-    sleep_time = float(kwargs.get('sleep_time', 3000)) / 1000

-    max_vms = int(kwargs.get('max_vms', stress_config.max_instances))

-    test_name = kwargs.get('test_name', 'unamed test')

-

-    keypath = stress_config.host_private_key_path

-    user = stress_config.host_admin_user

-    logdir = stress_config.nova_logdir

-    computes = _get_compute_nodes(keypath, user, manager.config.identity.host)

-    utils.util.execute_on_all(keypath, user, computes,

-                              "rm -f %s/*.log" % logdir)

-    random.seed(seed)

-    cases = _create_cases(choice_spec)

-    test_end_time = time.time() + duration.seconds

-    state = State(max_vms=max_vms)

-

-    retry_list = []

-    last_retry = time.time()

-    cooldown = False

-    logcheck_count = 0

-    test_succeeded = True

-    logging.debug('=== Test \"%s\" on %s ===' %

-                  (test_name, time.asctime(time.localtime())))

-    for kw in kwargs:

-        logging.debug('\t%s = %s', kw, kwargs[kw])

-

-    while True:

-        if not cooldown:

-            if time.time() < test_end_time:

-                case = random.choice(cases)

-                logging.debug('Chose %s' % case)

-                retry = case.invoke(manager, state)

-                if retry != None:

-                    retry_list.append(retry)

-            else:

-                logging.info('Cooling down...')

-                cooldown = True

-        if cooldown and len(retry_list) == 0:

-            if _error_in_logs(keypath, logdir, user, computes):

-                test_succeeded = False

-            break

-        # Retry verifications every 5 seconds.

-        if time.time() - last_retry > 5:

-            logging.debug('retry verifications for %d tasks', len(retry_list))

-            new_retry_list = []

-            for v in retry_list:

-                if not v.retry():

-                    new_retry_list.append(v)

-            retry_list = new_retry_list

-            last_retry = time.time()

-        time.sleep(sleep_time)

-        # Check error logs after 100 actions

-        if logcheck_count > 100:

-            if _error_in_logs(keypath, logdir, user, computes):

-                test_succeeded = False

-                break

-            else:

-                logcheck_count = 0

-        else:

-            logcheck_count = logcheck_count + 1

-    # Cleanup

-    logging.info('Cleaning up: terminating virtual machines...')

-    vms = state.get_instances()

-    active_vms = [v for _k, v in vms.iteritems() if v and v[1] == 'ACTIVE']

-    for target in active_vms:

-        manager.servers_client.delete_server(target[0]['id'])

-        # check to see that the server was actually killed

-    for target in active_vms:

-        kill_id = target[0]['id']

-        i = 0

-        while True:

-            try:

-                manager.servers_client.get_server(kill_id)

-            except Exception:

-                break

-            i += 1

-            if i > 60:

-                _error_in_logs(keypath, logdir, user, computes)

-                raise Exception("Cleanup timed out")

-            time.sleep(1)

-        logging.info('killed %s' % kill_id)

-        state.delete_instance_state(kill_id)

-

-    if test_succeeded:

-        logging.info('*** Test succeeded ***')

-    else:

-        logging.info('*** Test had errors ***')

-    return test_succeeded

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""The entry point for the execution of a workloadTo execute a workload.
+Users pass in a description of the workload and a nova manager object
+to the bash_openstack function call"""
+
+
+import random
+import datetime
+import time
+
+
+# local imports
+from test_case import *
+from state import State
+import utils.util
+from config import StressConfig
+
+# setup logging to file
+logging.basicConfig(
+    format='%(asctime)s %(name)-20s %(levelname)-8s %(message)s',
+    datefmt='%m-%d %H:%M:%S',
+    filename="stress.debug.log",
+    filemode="w",
+    level=logging.DEBUG,
+    )
+
+# define a Handler which writes INFO messages or higher to the sys.stdout
+_console = logging.StreamHandler()
+_console.setLevel(logging.INFO)
+# set a format which is simpler for console use
+_formatter = logging.Formatter('%(name)-20s: %(levelname)-8s %(message)s')
+# tell the handler to use this format
+_console.setFormatter(_formatter)
+# add the handler to the root logger
+logging.getLogger('').addHandler(_console)
+
+
+def _create_cases(choice_spec):
+    """
+    Generate a workload of tests from workload description
+    """
+    cases = []
+    count = 0
+    for choice in choice_spec:
+        p = choice.probability
+        for i in range(p):
+            cases.append(choice)
+        i = i + p
+        count = count + p
+    assert(count == 100)
+    return cases
+
+
+def _get_compute_nodes(keypath, user, controller):
+    """
+    Returns a list of active compute nodes. List is generated by running
+    nova-manage on the controller.
+    """
+    nodes = []
+    if keypath == None or user == None:
+        return nodes
+    lines = utils.util.ssh(keypath, user, controller,
+                     "nova-manage service list | grep ^nova-compute").\
+                     split('\n')
+    # For example: nova-compute xg11eth0 nova enabled :-) 2011-10-31 18:57:46
+    # This is fragile but there is, at present, no other way to get this info.
+    for line in lines:
+        words = line.split()
+        if len(words) > 0 and words[4] == ":-)":
+            nodes.append(words[1])
+    return nodes
+
+
+def _error_in_logs(keypath, logdir, user, nodes):
+    """
+    Detect errors in the nova log files on the controller and compute nodes.
+    """
+    grep = 'egrep "ERROR\|TRACE" %s/*.log' % logdir
+    for node in nodes:
+        errors = utils.util.ssh(keypath, user, node, grep, check=False)
+        if len(errors) > 0:
+            logging.error('%s: %s' % (node, errors))
+            return True
+    return False
+
+
+def bash_openstack(manager,
+                   choice_spec,
+                   **kwargs):
+    """
+    Workload driver. Executes a workload as specified by the `choice_spec`
+    parameter against a nova-cluster.
+
+    `manager`  : Manager object
+    `choice_spec` : list of BasherChoice actions to run on the cluster
+    `kargs`       : keyword arguments to the constructor of `test_case`
+                    `duration`   = how long this test should last (3 sec)
+                    `sleep_time` = time to sleep between actions (in msec)
+                    `test_name`  = human readable workload description
+                                   (default: unnamed test)
+                    `max_vms`    = maximum number of instances to launch
+                                   (default: 32)
+                    `seed`       = random seed (default: None)
+    """
+    stress_config = StressConfig(manager.config._conf)
+    # get keyword arguments
+    duration = kwargs.get('duration', datetime.timedelta(seconds=10))
+    seed = kwargs.get('seed', None)
+    sleep_time = float(kwargs.get('sleep_time', 3000)) / 1000
+    max_vms = int(kwargs.get('max_vms', stress_config.max_instances))
+    test_name = kwargs.get('test_name', 'unamed test')
+
+    keypath = stress_config.host_private_key_path
+    user = stress_config.host_admin_user
+    logdir = stress_config.nova_logdir
+    computes = _get_compute_nodes(keypath, user, manager.config.identity.host)
+    utils.util.execute_on_all(keypath, user, computes,
+                              "rm -f %s/*.log" % logdir)
+    random.seed(seed)
+    cases = _create_cases(choice_spec)
+    test_end_time = time.time() + duration.seconds
+    state = State(max_vms=max_vms)
+
+    retry_list = []
+    last_retry = time.time()
+    cooldown = False
+    logcheck_count = 0
+    test_succeeded = True
+    logging.debug('=== Test \"%s\" on %s ===' %
+                  (test_name, time.asctime(time.localtime())))
+    for kw in kwargs:
+        logging.debug('\t%s = %s', kw, kwargs[kw])
+
+    while True:
+        if not cooldown:
+            if time.time() < test_end_time:
+                case = random.choice(cases)
+                logging.debug('Chose %s' % case)
+                retry = case.invoke(manager, state)
+                if retry != None:
+                    retry_list.append(retry)
+            else:
+                logging.info('Cooling down...')
+                cooldown = True
+        if cooldown and len(retry_list) == 0:
+            if _error_in_logs(keypath, logdir, user, computes):
+                test_succeeded = False
+            break
+        # Retry verifications every 5 seconds.
+        if time.time() - last_retry > 5:
+            logging.debug('retry verifications for %d tasks', len(retry_list))
+            new_retry_list = []
+            for v in retry_list:
+                if not v.retry():
+                    new_retry_list.append(v)
+            retry_list = new_retry_list
+            last_retry = time.time()
+        time.sleep(sleep_time)
+        # Check error logs after 100 actions
+        if logcheck_count > 100:
+            if _error_in_logs(keypath, logdir, user, computes):
+                test_succeeded = False
+                break
+            else:
+                logcheck_count = 0
+        else:
+            logcheck_count = logcheck_count + 1
+    # Cleanup
+    logging.info('Cleaning up: terminating virtual machines...')
+    vms = state.get_instances()
+    active_vms = [v for _k, v in vms.iteritems() if v and v[1] == 'ACTIVE']
+    for target in active_vms:
+        manager.servers_client.delete_server(target[0]['id'])
+        # check to see that the server was actually killed
+    for target in active_vms:
+        kill_id = target[0]['id']
+        i = 0
+        while True:
+            try:
+                manager.servers_client.get_server(kill_id)
+            except Exception:
+                break
+            i += 1
+            if i > 60:
+                _error_in_logs(keypath, logdir, user, computes)
+                raise Exception("Cleanup timed out")
+            time.sleep(1)
+        logging.info('killed %s' % kill_id)
+        state.delete_instance_state(kill_id)
+
+    if test_succeeded:
+        logging.info('*** Test succeeded ***')
+    else:
+        logging.info('*** Test had errors ***')
+    return test_succeeded
diff --git a/stress/state.py b/stress/state.py
index c7eac37..60b1acc 100644
--- a/stress/state.py
+++ b/stress/state.py
@@ -1,41 +1,41 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""A class to store the state of various persistent objects in the Nova

-cluster, e.g. instances, volumes.  Use methods to query to state which than

-can be compared to the current state of the objects in Nova"""

-

-

-class State(object):

-

-    def __init__(self, **kwargs):

-        self._max_vms = kwargs.get('max_vms', 32)

-        self._instances = {}

-        self._volumes = {}

-

-    # machine state methods

-    def get_instances(self):

-        """return the instances dictionary that we believe are in cluster."""

-        return self._instances

-

-    def get_max_instances(self):

-        """return the maximum number of instances we can create."""

-        return self._max_vms

-

-    def set_instance_state(self, key, val):

-        """Store `val` in the dictionary indexed at `key`."""

-        self._instances[key] = val

-

-    def delete_instance_state(self, key):

-        """Delete state indexed at `key`."""

-        del self._instances[key]

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""A class to store the state of various persistent objects in the Nova
+cluster, e.g. instances, volumes.  Use methods to query to state which than
+can be compared to the current state of the objects in Nova"""
+
+
+class State(object):
+
+    def __init__(self, **kwargs):
+        self._max_vms = kwargs.get('max_vms', 32)
+        self._instances = {}
+        self._volumes = {}
+
+    # machine state methods
+    def get_instances(self):
+        """return the instances dictionary that we believe are in cluster."""
+        return self._instances
+
+    def get_max_instances(self):
+        """return the maximum number of instances we can create."""
+        return self._max_vms
+
+    def set_instance_state(self, key, val):
+        """Store `val` in the dictionary indexed at `key`."""
+        self._instances[key] = val
+
+    def delete_instance_state(self, key):
+        """Delete state indexed at `key`."""
+        del self._instances[key]
diff --git a/stress/test_case.py b/stress/test_case.py
index a9d2d20..fe510d5 100644
--- a/stress/test_case.py
+++ b/stress/test_case.py
@@ -1,29 +1,29 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""Abstract class for implementing an action. You only need to override

-the `run` method which specifies all the actual nova API class you wish

-to make."""

-

-

-import logging

-

-

-class StressTestCase(object):

-

-    def __init__(self):

-        self._logger = logging.getLogger(self.__class__.__name__)

-

-    def run(self, nova_manager, state_obj, *pargs, **kargs):

-        """Nova API methods to call that would modify state of the cluster"""

-        return

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""Abstract class for implementing an action. You only need to override
+the `run` method which specifies all the actual nova API class you wish
+to make."""
+
+
+import logging
+
+
+class StressTestCase(object):
+
+    def __init__(self):
+        self._logger = logging.getLogger(self.__class__.__name__)
+
+    def run(self, nova_manager, state_obj, *pargs, **kargs):
+        """Nova API methods to call that would modify state of the cluster"""
+        return
diff --git a/stress/tests/create_kill.py b/stress/tests/create_kill.py
index 8169fc4..26600de 100644
--- a/stress/tests/create_kill.py
+++ b/stress/tests/create_kill.py
@@ -1,35 +1,35 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""More aggressive test that creates and destroys VMs with shorter

-sleep times"""

-

-from stress.test_servers import *

-from stress.basher import BasherAction

-from stress.driver import *

-from tempest import openstack

-

-choice_spec = [

-    BasherAction(TestCreateVM(), 50),

-    BasherAction(TestKillActiveVM(), 50)

-]

-

-nova = openstack.Manager()

-

-bash_openstack(nova,

-               choice_spec,

-               duration=datetime.timedelta(seconds=180),

-               sleep_time=100,  # in milliseconds

-               seed=int(time.time()),

-               test_name="create and delete",

-               )

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""More aggressive test that creates and destroys VMs with shorter
+sleep times"""
+
+from stress.test_servers import *
+from stress.basher import BasherAction
+from stress.driver import *
+from tempest import openstack
+
+choice_spec = [
+    BasherAction(TestCreateVM(), 50),
+    BasherAction(TestKillActiveVM(), 50)
+]
+
+nova = openstack.Manager()
+
+bash_openstack(nova,
+               choice_spec,
+               duration=datetime.timedelta(seconds=180),
+               sleep_time=100,  # in milliseconds
+               seed=int(time.time()),
+               test_name="create and delete",
+               )
diff --git a/stress/tests/hard_reboots.py b/stress/tests/hard_reboots.py
index 1b5928e..324b133 100644
--- a/stress/tests/hard_reboots.py
+++ b/stress/tests/hard_reboots.py
@@ -1,37 +1,37 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""Test that reboots random instances in a Nova cluster"""

-

-

-from stress.test_servers import *

-from stress.test_server_actions import *

-from stress.basher import BasherAction

-from stress.driver import *

-from tempest import openstack

-

-choice_spec = [

-    BasherAction(TestCreateVM(), 50),

-    BasherAction(TestRebootVM(), 50,

-                 kargs={'type': 'HARD'})

-]

-

-nova = openstack.Manager()

-

-bash_openstack(nova,

-               choice_spec,

-               duration=datetime.timedelta(seconds=180),

-               sleep_time=500,  # in milliseconds

-               seed=int(time.time()),

-               test_name="hard reboots",

-               )

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""Test that reboots random instances in a Nova cluster"""
+
+
+from stress.test_servers import *
+from stress.test_server_actions import *
+from stress.basher import BasherAction
+from stress.driver import *
+from tempest import openstack
+
+choice_spec = [
+    BasherAction(TestCreateVM(), 50),
+    BasherAction(TestRebootVM(), 50,
+                 kargs={'type': 'HARD'})
+]
+
+nova = openstack.Manager()
+
+bash_openstack(nova,
+               choice_spec,
+               duration=datetime.timedelta(seconds=180),
+               sleep_time=500,  # in milliseconds
+               seed=int(time.time()),
+               test_name="hard reboots",
+               )
diff --git a/stress/tests/user_script_sample.py b/stress/tests/user_script_sample.py
index 3a6972c..51270a7 100644
--- a/stress/tests/user_script_sample.py
+++ b/stress/tests/user_script_sample.py
@@ -1,38 +1,38 @@
-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-"""Sample stress test that creates a few virtual machines and then

-destroys them"""

-

-

-from stress.test_servers import *

-from stress.basher import BasherAction

-from stress.driver import *

-from tempest import openstack

-

-choice_spec = [

-    BasherAction(TestCreateVM(), 50,

-                 kargs={'timeout': '60'}),

-    BasherAction(TestKillActiveVM(), 50)

-]

-

-

-nova = openstack.Manager()

-

-bash_openstack(nova,

-               choice_spec,

-               duration=datetime.timedelta(seconds=10),

-               sleep_time=1000,  # in milliseconds

-               seed=None,

-               test_name="simple create and delete",

-               max_vms=4)

+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+"""Sample stress test that creates a few virtual machines and then
+destroys them"""
+
+
+from stress.test_servers import *
+from stress.basher import BasherAction
+from stress.driver import *
+from tempest import openstack
+
+choice_spec = [
+    BasherAction(TestCreateVM(), 50,
+                 kargs={'timeout': '60'}),
+    BasherAction(TestKillActiveVM(), 50)
+]
+
+
+nova = openstack.Manager()
+
+bash_openstack(nova,
+               choice_spec,
+               duration=datetime.timedelta(seconds=10),
+               sleep_time=1000,  # in milliseconds
+               seed=None,
+               test_name="simple create and delete",
+               max_vms=4)
diff --git a/stress/tools/nova_destroy_all.py b/stress/tools/nova_destroy_all.py
index 3816557..e9010cd 100755
--- a/stress/tools/nova_destroy_all.py
+++ b/stress/tools/nova_destroy_all.py
@@ -1,54 +1,54 @@
-#!/usr/bin/env python

-

-# vim: tabstop=4 shiftwidth=4 softtabstop=4

-

-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-

-from novaclient.v1_1 import client

-import tempest.config

-

-# get the environment variables for credentials

-identity = tempest.config.TempestConfig().identity

-compute = tempest.config.TempestConfig().compute

-

-nt = client.Client(compute.username, compute.password,

-                   compute.tenant_name, identity.auth_url)

-

-flavor_list = nt.flavors.list()

-server_list = nt.servers.list()

-images_list = nt.images.list()

-keypairs_list = nt.keypairs.list()

-floating_ips_list = nt.floating_ips.list()

-

-print "total servers: %3d, total flavors: %3d, total images: %3d," % \

-    (len(server_list),

-     len(flavor_list),

-     len(images_list)),

-

-print "total keypairs: %3d, total floating ips: %3d" % \

-    (len(keypairs_list),

-     len(floating_ips_list))

-

-print "deleting all servers"

-for s in server_list:

-    s.delete()

-

-print "deleting all keypairs"

-for s in keypairs_list:

-    s.delete()

-

-print "deleting all floating_ips"

-for s in floating_ips_list:

-    s.delete()

+#!/usr/bin/env python
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+
+from novaclient.v1_1 import client
+import tempest.config
+
+# get the environment variables for credentials
+identity = tempest.config.TempestConfig().identity
+compute = tempest.config.TempestConfig().compute
+
+nt = client.Client(compute.username, compute.password,
+                   compute.tenant_name, identity.auth_url)
+
+flavor_list = nt.flavors.list()
+server_list = nt.servers.list()
+images_list = nt.images.list()
+keypairs_list = nt.keypairs.list()
+floating_ips_list = nt.floating_ips.list()
+
+print "total servers: %3d, total flavors: %3d, total images: %3d," % \
+    (len(server_list),
+     len(flavor_list),
+     len(images_list)),
+
+print "total keypairs: %3d, total floating ips: %3d" % \
+    (len(keypairs_list),
+     len(floating_ips_list))
+
+print "deleting all servers"
+for s in server_list:
+    s.delete()
+
+print "deleting all keypairs"
+for s in keypairs_list:
+    s.delete()
+
+print "deleting all floating_ips"
+for s in floating_ips_list:
+    s.delete()
diff --git a/stress/tools/nova_status.py b/stress/tools/nova_status.py
index c0b7893..d413d7a 100755
--- a/stress/tools/nova_status.py
+++ b/stress/tools/nova_status.py
@@ -1,50 +1,50 @@
-#!/usr/bin/env python

-

-# vim: tabstop=4 shiftwidth=4 softtabstop=4

-

-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-

-from novaclient.v1_1 import client

-import tempest.config

-

-# get the environment variables for credentials

-identity = tempest.config.TempestConfig().identity

-compute = tempest.config.TempestConfig().compute

-print compute.username, compute.password,\

-    compute.tenant_name, identity.auth_url

-

-nt = client.Client(compute.username, compute.password,

-                   compute.tenant_name, identity.auth_url)

-

-flavor_list = nt.flavors.list()

-server_list = nt.servers.list()

-images_list = nt.images.list()

-keypairs_list = nt.keypairs.list()

-floating_ips_list = nt.floating_ips.list()

-

-print "total servers: %3d, total flavors: %3d, total images: %3d" % \

-    (len(server_list),

-     len(flavor_list),

-     len(images_list))

-

-print "total keypairs: %3d, total floating ips: %3d" % \

-    (len(keypairs_list),

-     len(floating_ips_list))

-

-print "flavors:\t", flavor_list

-print "servers:\t", server_list

-print "images: \t", images_list

-print "keypairs:\t", keypairs_list

-print "floating ips:\t", floating_ips_list

+#!/usr/bin/env python
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+
+from novaclient.v1_1 import client
+import tempest.config
+
+# get the environment variables for credentials
+identity = tempest.config.TempestConfig().identity
+compute = tempest.config.TempestConfig().compute
+print compute.username, compute.password,\
+    compute.tenant_name, identity.auth_url
+
+nt = client.Client(compute.username, compute.password,
+                   compute.tenant_name, identity.auth_url)
+
+flavor_list = nt.flavors.list()
+server_list = nt.servers.list()
+images_list = nt.images.list()
+keypairs_list = nt.keypairs.list()
+floating_ips_list = nt.floating_ips.list()
+
+print "total servers: %3d, total flavors: %3d, total images: %3d" % \
+    (len(server_list),
+     len(flavor_list),
+     len(images_list))
+
+print "total keypairs: %3d, total floating ips: %3d" % \
+    (len(keypairs_list),
+     len(floating_ips_list))
+
+print "flavors:\t", flavor_list
+print "servers:\t", server_list
+print "images: \t", images_list
+print "keypairs:\t", keypairs_list
+print "floating ips:\t", floating_ips_list
diff --git a/stress/utils/__init__.py b/stress/utils/__init__.py
index d4ac711..85300f2 100644
--- a/stress/utils/__init__.py
+++ b/stress/utils/__init__.py
@@ -1,15 +1,15 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4

-

-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
diff --git a/stress/utils/util.py b/stress/utils/util.py
index ac8f062..5870ca1 100644
--- a/stress/utils/util.py
+++ b/stress/utils/util.py
@@ -1,55 +1,55 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4

-

-# Copyright 2011 Quanta Research Cambridge, Inc.

-#

-#    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.

-

-import subprocess

-import shlex

-

-SSH_OPTIONS = (" -q" +

-               " -o UserKnownHostsFile=/dev/null" +

-               " -o StrictHostKeyChecking=no -i ")

-

-

-def get_ssh_options(keypath):

-    return SSH_OPTIONS + keypath

-

-

-def scp(keypath, args):

-    options = get_ssh_options(keypath)

-    return subprocess.check_call(shlex.split("scp" + options + args))

-

-

-def ssh(keypath, user, node, command, check=True):

-    command = 'sudo ' + command

-    command = "ssh %s %s@%s %s" % (get_ssh_options(keypath), user,

-                                   node, command)

-    popenargs = shlex.split(command)

-    process = subprocess.Popen(popenargs, stdout=subprocess.PIPE)

-    output, unused_err = process.communicate()

-    retcode = process.poll()

-    if retcode and check:

-        raise Exception("%s: ssh failed with retcode: %s" % (node, retcode))

-    return output

-

-

-def execute_on_all(keypath, user, nodes, command):

-    for node in nodes:

-        ssh(keypath, user, node, command)

-

-

-def enum(*sequential, **named):

-    """Create auto-incremented enumerated types"""

-    enums = dict(zip(sequential, range(len(sequential))), **named)

-    return type('Enum', (), enums)

+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Quanta Research Cambridge, Inc.
+#
+#    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.
+
+import subprocess
+import shlex
+
+SSH_OPTIONS = (" -q" +
+               " -o UserKnownHostsFile=/dev/null" +
+               " -o StrictHostKeyChecking=no -i ")
+
+
+def get_ssh_options(keypath):
+    return SSH_OPTIONS + keypath
+
+
+def scp(keypath, args):
+    options = get_ssh_options(keypath)
+    return subprocess.check_call(shlex.split("scp" + options + args))
+
+
+def ssh(keypath, user, node, command, check=True):
+    command = 'sudo ' + command
+    command = "ssh %s %s@%s %s" % (get_ssh_options(keypath), user,
+                                   node, command)
+    popenargs = shlex.split(command)
+    process = subprocess.Popen(popenargs, stdout=subprocess.PIPE)
+    output, unused_err = process.communicate()
+    retcode = process.poll()
+    if retcode and check:
+        raise Exception("%s: ssh failed with retcode: %s" % (node, retcode))
+    return output
+
+
+def execute_on_all(keypath, user, nodes, command):
+    for node in nodes:
+        ssh(keypath, user, node, command)
+
+
+def enum(*sequential, **named):
+    """Create auto-incremented enumerated types"""
+    enums = dict(zip(sequential, range(len(sequential))), **named)
+    return type('Enum', (), enums)