<commit_before># -*- coding: utf-8 -*-
"""
Display network transfer rate.

Configuration parameters:
    all_interfaces: ignore self.interfaces, but not self.interfaces_blacklist
        (default True)
    cache_timeout: how often we refresh this module in seconds
        (default 2)
    devfile: location of dev file under /proc
        (default '/proc/net/dev')
    format: format of the module output
        (default '{interface}: {total}')
    format_no_connection: when there is no data transmitted from the start of the plugin
        (default '')
    format_value: format to use for values
        (default "[\?min_length=11 {value:.1f} {unit}]")
    hide_if_zero: hide indicator if rate == 0
        (default False)
    interfaces: comma separated list of interfaces to track
        (default [])
    interfaces_blacklist: comma separated list of interfaces to ignore
        (default 'lo')
    si_units: use SI units
        (default False)
    sum_values: sum values of each interface instead of taking the top one
        (default False)
    thresholds: thresholds to use for colors
        (default [(0, 'bad'), (1024, 'degraded'), (1024 * 1024, 'good')])
    unit: unit to use. If the unit contains a multiplier prefix, only this
        exact unit will ever be used
        (default "B/s")

Format placeholders:
    {down} download rate
    {interface} name of interface
    {total} total rate
    {up} upload rate

format_value placeholders:
    {unit} current unit
    {value} numeric value

Color thresholds:
    {down} Change color based on the value of down
    {total} Change color based on the value of total
    {up} Change color based on the value of up

@author shadowprince
@license Eclipse Public License

SAMPLE OUTPUT
{'full_text': 'eno1:  852.2 KiB/s'}
"""

from __future__ import division  # python2 compatibility
from time import time

class Py3status:
    """
    """

    # available configuration parameters
    all_interfaces = True
    cache_timeout = 2
    devfile = "/proc/net/dev"
    format = "{interface}: {total}"
    format_no_connection = ""
    format_value = "[\?min_length=11 {value:.1f} {unit}]"
    hide_if_zero = False
    interfaces = []
    interfaces_blacklist = "lo"
    si_units = False
    sum_values = False
    thresholds = [(0, "bad"), (1024, "degraded"), (1024 * 1024, "good")]
    unit = "B/s"

    class Meta:
        def deprecate_function(config):
            # support old thresholds
            precision = config.get("precision", 1)
            padding = 3 + 1 + precision + 1 + 5
            format_value = "[\?min_length={padding} {{value:.{precision}f}} {{unit}}]".format(
                padding=padding, precision=precision
            )
            return {"format_value": format_value}

        deprecated = {
            "function": [{"function": deprecate_function}],
            "remove": [
                {"param": "precision", "msg": "obsolete, use format_value instead"}
            ],
        }

    def post_config_hook(self):
        # parse some configuration parameters
        if not isinstance(self.interfaces, list):
            self.interfaces = self.interfaces.split(",")
        if not isinstance(self.interfaces_blacklist, list):
            self.interfaces_blacklist = self.interfaces_blacklist.split(",")
        placeholders = self.py3.get_placeholder_formats_list(self.format_value)
        values = ["{%s}" % x[1] for x in placeholders if x[0] == "value"]
        self._value_formats = values
        # last
        self.last_interface = None
        self.last_stat = self._get_stat()
        self.last_time = time()

        self.thresholds_init = self.py3.get_color_names_list(self.format)

    def net_rate(self):
        ns = self._get_stat()
        deltas = {}
        try:
            # time from previous check
            timedelta = time() - self.last_time

            # calculate deltas for all interfaces
            for old, new in zip(self.last_stat, ns):
                down = int(new[1]) - int(old[1])
                up = int(new[9]) - int(old[9])

                down /= timedelta
                up /= timedelta

                deltas[new[0]] = {"total": up + down, "up": up, "down": down}

            # update last_ info
            self.last_stat = self._get_stat()
            self.last_time = time()

            # get the interface with max rate
            if self.sum_values:
                interface = "sum"
                sum_up = sum([itm["up"] for _, itm in deltas.items()])
                sum_down = sum([itm["down"] for _, itm in deltas.items()])
                deltas[interface] = {
                    "total": sum_up + sum_down,
                    "up": sum_up,
                    "down": sum_down,
                }
            else:
                interface = max(deltas, key=lambda x: deltas[x]["total"])

            # if there is no rate - show last active interface, or hide

            # we need to check if it will be zero after it is formatted
            # with the desired unit eg MB/s
            total, _ = self.py3.format_units(
                deltas[interface]["total"], unit=self.unit, si=self.si_units
            )
            values = [float(x.format(total)) for x in self._value_formats]
            if max(values) == 0:
                interface = self.last_interface
                hide = self.hide_if_zero
            # if there is - update last_interface
            else:
                self.last_interface = interface
                hide = False

            # get the deltas into variable
            delta = deltas[interface] if interface else None

        except (TypeError, ValueError):
            delta = None
            interface = None
            hide = self.hide_if_zero

        response = {"cached_until": self.py3.time_in(self.cache_timeout)}

        if hide:
            response["full_text"] = ""
        elif not interface:
            response["full_text"] = self.format_no_connection
        else:
            for x in self.thresholds_init:
                if x in delta:
                    self.py3.threshold_get_color(delta[x], x)

            response["full_text"] = self.py3.safe_format(
                self.format,
                {
                    "down": self._format_value(delta["down"]),
                    "total": self._format_value(delta["total"]),
                    "up": self._format_value(delta["up"]),
                    "interface": interface[:-1],
                },
            )

        return response

    def _get_stat(self):
        """
        Get statistics from devfile in list of lists of words
        """

        def dev_filter(x):
            # get first word and remove trailing interface number
            x = x.strip().split(" ")[0][:-1]

            if x in self.interfaces_blacklist:
                return False

            if self.all_interfaces:
                return True

            if x in self.interfaces:
                return True

            return False

        # read devfile, skip two header files
        x = filter(dev_filter, open(self.devfile).readlines()[2:])

        try:
            # split info into words, filter empty ones
            return [list(filter(lambda x: x, _x.split(" "))) for _x in x]

        except StopIteration:
            return None

    def _format_value(self, value):
        """
        Return formatted string
        """
        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)
        return self.py3.safe_format(self.format_value, {"value": value, "unit": unit})

if __name__ == "__main__":
    """
    Run module in test mode.
    """
    from py3status.module_test import module_test

    module_test(Py3status)
<commit_msg>net_rate: prevent errors after resuming from sleep (#1659)<commit_after># -*- coding: utf-8 -*-
"""
Display network transfer rate.

Configuration parameters:
    all_interfaces: ignore self.interfaces, but not self.interfaces_blacklist
        (default True)
    cache_timeout: how often we refresh this module in seconds
        (default 2)
    devfile: location of dev file under /proc
        (default '/proc/net/dev')
    format: format of the module output
        (default '{interface}: {total}')
    format_no_connection: when there is no data transmitted from the start of the plugin
        (default '')
    format_value: format to use for values
        (default "[\?min_length=11 {value:.1f} {unit}]")
    hide_if_zero: hide indicator if rate == 0
        (default False)
    interfaces: comma separated list of interfaces to track
        (default [])
    interfaces_blacklist: comma separated list of interfaces to ignore
        (default 'lo')
    si_units: use SI units
        (default False)
    sum_values: sum values of each interface instead of taking the top one
        (default False)
    thresholds: thresholds to use for colors
        (default [(0, 'bad'), (1024, 'degraded'), (1024 * 1024, 'good')])
    unit: unit to use. If the unit contains a multiplier prefix, only this
        exact unit will ever be used
        (default "B/s")

Format placeholders:
    {down} download rate
    {interface} name of interface
    {total} total rate
    {up} upload rate

format_value placeholders:
    {unit} current unit
    {value} numeric value

Color thresholds:
    {down} Change color based on the value of down
    {total} Change color based on the value of total
    {up} Change color based on the value of up

@author shadowprince
@license Eclipse Public License

SAMPLE OUTPUT
{'full_text': 'eno1:  852.2 KiB/s'}
"""

from __future__ import division  # python2 compatibility
from time import time

class Py3status:
    """
    """

    # available configuration parameters
    all_interfaces = True
    cache_timeout = 2
    devfile = "/proc/net/dev"
    format = "{interface}: {total}"
    format_no_connection = ""
    format_value = "[\?min_length=11 {value:.1f} {unit}]"
    hide_if_zero = False
    interfaces = []
    interfaces_blacklist = "lo"
    si_units = False
    sum_values = False
    thresholds = [(0, "bad"), (1024, "degraded"), (1024 * 1024, "good")]
    unit = "B/s"

    class Meta:
        def deprecate_function(config):
            # support old thresholds
            precision = config.get("precision", 1)
            padding = 3 + 1 + precision + 1 + 5
            format_value = "[\?min_length={padding} {{value:.{precision}f}} {{unit}}]".format(
                padding=padding, precision=precision
            )
            return {"format_value": format_value}

        deprecated = {
            "function": [{"function": deprecate_function}],
            "remove": [
                {"param": "precision", "msg": "obsolete, use format_value instead"}
            ],
        }

    def post_config_hook(self):
        # parse some configuration parameters
        if not isinstance(self.interfaces, list):
            self.interfaces = self.interfaces.split(",")
        if not isinstance(self.interfaces_blacklist, list):
            self.interfaces_blacklist = self.interfaces_blacklist.split(",")
        placeholders = self.py3.get_placeholder_formats_list(self.format_value)
        values = ["{%s}" % x[1] for x in placeholders if x[0] == "value"]
        self._value_formats = values
        # last
        self.last_interface = None
        self.last_stat = self._get_stat()
        self.last_time = time()

        self.thresholds_init = self.py3.get_color_names_list(self.format)

    def net_rate(self):
        ns = self._get_stat()
        deltas = {}
        try:
            # time from previous check
            timedelta = time() - self.last_time

            # calculate deltas for all interfaces
            for old, new in zip(self.last_stat, ns):
                down = int(new[1]) - int(old[1])
                up = int(new[9]) - int(old[9])

                down /= timedelta
                up /= timedelta

                deltas[new[0]] = {"total": up + down, "up": up, "down": down}

            # update last_ info
            self.last_stat = self._get_stat()
            self.last_time = time()

            # get the interface with max rate
            if self.sum_values:
                interface = "sum"
                sum_up = sum([itm["up"] for _, itm in deltas.items()])
                sum_down = sum([itm["down"] for _, itm in deltas.items()])
                deltas[interface] = {
                    "total": sum_up + sum_down,
                    "up": sum_up,
                    "down": sum_down,
                }
            else:
                interface = max(deltas, key=lambda x: deltas[x]["total"])

            # if there is no rate - show last active interface, or hide

            # we need to check if it will be zero after it is formatted
            # with the desired unit eg MB/s
            total, _ = self.py3.format_units(
                deltas[interface]["total"], unit=self.unit, si=self.si_units
            )
            values = [float(x.format(total)) for x in self._value_formats]
            if max(values) == 0:
                interface = self.last_interface
                hide = self.hide_if_zero
            # if there is - update last_interface
            else:
                self.last_interface = interface
                hide = False

            # get the deltas into variable
            delta = deltas[interface] if interface else None

        except (TypeError, ValueError, KeyError):
            delta = None
            interface = None
            hide = self.hide_if_zero

        response = {"cached_until": self.py3.time_in(self.cache_timeout)}

        if hide:
            response["full_text"] = ""
        elif not interface:
            response["full_text"] = self.format_no_connection
        else:
            for x in self.thresholds_init:
                if x in delta:
                    self.py3.threshold_get_color(delta[x], x)

            response["full_text"] = self.py3.safe_format(
                self.format,
                {
                    "down": self._format_value(delta["down"]),
                    "total": self._format_value(delta["total"]),
                    "up": self._format_value(delta["up"]),
                    "interface": interface[:-1],
                },
            )

        return response

    def _get_stat(self):
        """
        Get statistics from devfile in list of lists of words
        """

        def dev_filter(x):
            # get first word and remove trailing interface number
            x = x.strip().split(" ")[0][:-1]

            if x in self.interfaces_blacklist:
                return False

            if self.all_interfaces:
                return True

            if x in self.interfaces:
                return True

            return False

        # read devfile, skip two header files
        x = filter(dev_filter, open(self.devfile).readlines()[2:])

        try:
            # split info into words, filter empty ones
            return [list(filter(lambda x: x, _x.split(" "))) for _x in x]

        except StopIteration:
            return None

    def _format_value(self, value):
        """
        Return formatted string
        """
        value, unit = self.py3.format_units(value, unit=self.unit, si=self.si_units)
        return self.py3.safe_format(self.format_value, {"value": value, "unit": unit})

if __name__ == "__main__":
    """
    Run module in test mode.
    """
    from py3status.module_test import module_test

    module_test(Py3status)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# @COPYRIGHT_begin
#
# Copyright [2015] Michał Szczygieł, M4GiK Software
#
# 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.
#
# @COPYRIGHT_end
from __future__ import absolute_import
import ast
from celery import Celery
from fabric.decorators import hosts
from fabric.operations import run
from fabric.tasks import execute
import jsonpickle
import paramiko
from core.common import states

from core.settings.common import settings, WAIT_TIME, LOOP_TIME
from core.settings.common import BROKER_URL, CELERY_RESULT_BACKEND
from core.settings.config import SSH_KEY_PATH, VM_IMAGE_ROOT_PASSWORD
from core.utils.auth import ROOT
from core.utils.decorators import dev_cloud_task
from core.utils.exception import DevCloudException
from database.models import Applications
from virtual_controller.cc1_module.check_quota import Quota
from virtual_controller.cc1_module.key import Key
from virtual_controller.cc1_module.public_ip import PoolIP
from django.utils.translation import ugettext as _

# os.environ.setdefault('CELERY_CONFIG_MODULE', "core.settings.%s" % args)
from virtual_controller.cc1_module.virtual_machine import VirtualMachine
from virtual_controller.juju_core.juju_installation_procedure import init_juju_on_vm
from virtual_controller.juju_core.run_cmd import RunCommand
from virtual_controller.juju_core.ssh_connector import SSHConnector

REQUEST_IP = _('Request new IP')
RELEASE_IP = _('Release IP')
CHECK_RESOURCE = _('Check resource')
CREATE_VM = _('Create new virtual machine')
GENERATE_SSH = _('Generate new SSH key pair')
INIT_VM = _('Initialize virtual machine')
DESTROY_VM = _('Destroy virtual machine')

app = Celery('core.utils', broker=BROKER_URL, backend=CELERY_RESULT_BACKEND, include=['core.utils'])

# Optional configuration, see the application user guide.
app.conf.update(
    CELERY_TASK_RESULT_EXPIRES=3600,
)

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object("django.conf:settings")
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

# if __name__ == '__main__':
# app.start()

@app.task(trail=True, name='core.utils.tasks.request')
@dev_cloud_task(REQUEST_IP)
def request(user_id):
    """
    Method to obtain public IP form CC1.
    @return: Obtained IP.
    """
    poolIP = PoolIP(user_id)
    poolIP.request()
    return poolIP.get_ip_address()

@app.task(trail=True, name='core.utils.tasks.release')
@dev_cloud_task(RELEASE_IP)
def release(user_id, ip_address):
    """
    Method to release public IP form CC1.
    @return: Status about removed ip address.
    """
    poolIP = PoolIP(user_id, ip_address)
    return poolIP.remove()

@app.task(trail=True, name='core.utils.tasks.check_resource')
@dev_cloud_task(CHECK_RESOURCE)
def check_resource(user_id, template_id):
    """
    Method to check available resource to create new virtual machine.
    @param user_id: id of caller.
    @param template_id: selected id for template.
    @return: Status about available resources. If is ok return 200, if not return 402.
    """
    quota = Quota(user_id)
    quota.check_quota(template_id)

    return quota.get_status()

@app.task(trail=True, name='core.utils.tasks.create_virtual_machine')
@dev_cloud_task(CREATE_VM)
def create_virtual_machine(user_id, vm_property):
    """
    Creates new instance of virtual machine on CC1, making a request.
    @param user_id: id of caller.
    @param vm_property: instance of virtual machine form with properties.
    @return: id of virtual machine.
    """
    virtual_machine = VirtualMachine(user_id, jsonpickle.decode(vm_property))
    return virtual_machine.create()

@app.task(trail=True, name='core.utils.tasks.get_virtual_machine_status')
def get_virtual_machine_status(user_id, vm_id):
    """
    Gets requested caller's virtual machine.
    @param user_id: id of caller.
    @param vm_id: id of virtual machine.
    @return: data contains information about virtual machine.
    """
    virtual_machine = VirtualMachine(user_id)
    return virtual_machine.get_vm_status(vm_id)

@app.task(trail=True, name='core.utils.tasks.generate_ssh_key')
@dev_cloud_task(GENERATE_SSH)
def generate_ssh_key(user_id, name):
    """
    Generates ssh key pair. Public part of that Key is
    stored in CC1 database with specified name, whereas content of the private Key
    part is returned and stored in DevCloud database.
    Neither public, nor private part of the key is saved to file.
    @param user_id: id of caller.
    @param name: Key's name.
    @return: Private part of the key.
    """
    key = Key(user_id, name)
    return key.generate()

@app.task(trail=True, name='core.utils.tasks.get_ssh_key')
def get_ssh_key(user_id, name):
    """
    Get ssh key. The public part.
    @param user_id: id of caller.
    @param name: Key's name.
    @return: Public part of the key.
    """
    key = Key(user_id, name)
    return key.get(name)

@app.task(trail=False, ignore_result=True, name='core.utils.tasks.init_virtual_machine')
@dev_cloud_task(INIT_VM)
def init_virtual_machine(user_id, vm_serializer_data, applications):
    """
    Initialize given virtual machine with selected application stored in database.
    @param user_id: id of caller.
    @param vm_serializer_data: serialized data contains information about virtual machines.
    @param applications: list of applications.
    @return:
    """
    is_timeout = False
    current_time = 0
    virtual_machine = VirtualMachine(user_id)
    while virtual_machine.get_vm_status(vm_serializer_data.get('vm_id')) != \
            [key for key, value in states.vm_states.iteritems() if value == 'running ctx'][0]:
        current_time += LOOP_TIME
        is_timeout = SSHConnector.timeout(WAIT_TIME, LOOP_TIME, current_time)
        if is_timeout:
            break

    if not is_timeout:
        # ssh = SSHConnector(virtual_machine.get_vm_private_ip(vm_serializer_data.get('vm_id')), ROOT,
        #                    SSH_KEY_PATH)
        #
        # ssh.exec_task(init_juju_on_vm)
        #
        # for application in ast.literal_eval(applications):
        #     app = Applications.objects.get(application_name=application)
        #     ssh.call_remote_command(app.instalation_procedure)
        ssh = RunCommand()
        ssh.do_add_host(virtual_machine.get_vm_private_ip(vm_serializer_data.get('vm_id')))
        ssh.do_connect()
        ssh.do_run('juju generate-config && juju switch local && juju bootstrap')
    else:
        raise Exception

@app.task(trail=False, ignore_result=True, name='core.utils.tasks.destroy_virtual_machine')
@dev_cloud_task(DESTROY_VM)
def destroy_virtual_machine(user_id, vm_id):
    """
    Destroys the given virtual machine.
    @param user_id: id of caller.
    @param vm_id: id of virtual machine.
    @return: OK if machine is properly destroyed or FAILED if not.
    """
    current_time = 0
    virtual_machine = VirtualMachine(user_id)
    while virtual_machine.get_vm_status(vm_id) != \
            [key for key, value in states.vm_states.iteritems() if value == 'running ctx'][0]:
        current_time += LOOP_TIME
        is_timeout = SSHConnector.timeout(WAIT_TIME, LOOP_TIME, current_time)
        if is_timeout:
            break

    virtual_machine = VirtualMachine(user_id)
    return virtual_machine.destroy(vm_id)
<commit_msg>#33 Change configuration for initialize<commit_after># -*- coding: utf-8 -*-
# @COPYRIGHT_begin
#
# Copyright [2015] Michał Szczygieł, M4GiK Software
#
# 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.
#
# @COPYRIGHT_end
from __future__ import absolute_import
import ast
from celery import Celery
from fabric.decorators import hosts
from fabric.operations import run
from fabric.tasks import execute
import jsonpickle
import paramiko
from core.common import states

from core.settings.common import settings, WAIT_TIME, LOOP_TIME
from core.settings.common import BROKER_URL, CELERY_RESULT_BACKEND
from core.settings.config import SSH_KEY_PATH, VM_IMAGE_ROOT_PASSWORD
from core.utils.auth import ROOT
from core.utils.decorators import dev_cloud_task
from core.utils.exception import DevCloudException
from database.models import Applications
from virtual_controller.cc1_module.check_quota import Quota
from virtual_controller.cc1_module.key import Key
from virtual_controller.cc1_module.public_ip import PoolIP
from django.utils.translation import ugettext as _

# os.environ.setdefault('CELERY_CONFIG_MODULE', "core.settings.%s" % args)
from virtual_controller.cc1_module.virtual_machine import VirtualMachine
from virtual_controller.juju_core.juju_installation_procedure import init_juju_on_vm
from virtual_controller.juju_core.run_cmd import RunCommand
from virtual_controller.juju_core.ssh_connector import SSHConnector

REQUEST_IP = _('Request new IP')
RELEASE_IP = _('Release IP')
CHECK_RESOURCE = _('Check resource')
CREATE_VM = _('Create new virtual machine')
GENERATE_SSH = _('Generate new SSH key pair')
INIT_VM = _('Initialize virtual machine')
DESTROY_VM = _('Destroy virtual machine')

app = Celery('core.utils', broker=BROKER_URL, backend=CELERY_RESULT_BACKEND, include=['core.utils'])

# Optional configuration, see the application user guide.
app.conf.update(
    CELERY_TASK_RESULT_EXPIRES=3600,
)

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object("django.conf:settings")
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

# if __name__ == '__main__':
# app.start()

@app.task(trail=True, name='core.utils.tasks.request')
@dev_cloud_task(REQUEST_IP)
def request(user_id):
    """
    Method to obtain public IP form CC1.
    @return: Obtained IP.
    """
    poolIP = PoolIP(user_id)
    poolIP.request()
    return poolIP.get_ip_address()

@app.task(trail=True, name='core.utils.tasks.release')
@dev_cloud_task(RELEASE_IP)
def release(user_id, ip_address):
    """
    Method to release public IP form CC1.
    @return: Status about removed ip address.
    """
    poolIP = PoolIP(user_id, ip_address)
    return poolIP.remove()

@app.task(trail=True, name='core.utils.tasks.check_resource')
@dev_cloud_task(CHECK_RESOURCE)
def check_resource(user_id, template_id):
    """
    Method to check available resource to create new virtual machine.
    @param user_id: id of caller.
    @param template_id: selected id for template.
    @return: Status about available resources. If is ok return 200, if not return 402.
    """
    quota = Quota(user_id)
    quota.check_quota(template_id)

    return quota.get_status()

@app.task(trail=True, name='core.utils.tasks.create_virtual_machine')
@dev_cloud_task(CREATE_VM)
def create_virtual_machine(user_id, vm_property):
    """
    Creates new instance of virtual machine on CC1, making a request.
    @param user_id: id of caller.
    @param vm_property: instance of virtual machine form with properties.
    @return: id of virtual machine.
    """
    virtual_machine = VirtualMachine(user_id, jsonpickle.decode(vm_property))
    return virtual_machine.create()

@app.task(trail=True, name='core.utils.tasks.get_virtual_machine_status')
def get_virtual_machine_status(user_id, vm_id):
    """
    Gets requested caller's virtual machine.
    @param user_id: id of caller.
    @param vm_id: id of virtual machine.
    @return: data contains information about virtual machine.
    """
    virtual_machine = VirtualMachine(user_id)
    return virtual_machine.get_vm_status(vm_id)

@app.task(trail=True, name='core.utils.tasks.generate_ssh_key')
@dev_cloud_task(GENERATE_SSH)
def generate_ssh_key(user_id, name):
    """
    Generates ssh key pair. Public part of that Key is
    stored in CC1 database with specified name, whereas content of the private Key
    part is returned and stored in DevCloud database.
    Neither public, nor private part of the key is saved to file.
    @param user_id: id of caller.
    @param name: Key's name.
    @return: Private part of the key.
    """
    key = Key(user_id, name)
    return key.generate()

@app.task(trail=True, name='core.utils.tasks.get_ssh_key')
def get_ssh_key(user_id, name):
    """
    Get ssh key. The public part.
    @param user_id: id of caller.
    @param name: Key's name.
    @return: Public part of the key.
    """
    key = Key(user_id, name)
    return key.get(name)

@app.task(trail=False, ignore_result=True, name='core.utils.tasks.init_virtual_machine')
@dev_cloud_task(INIT_VM)
def init_virtual_machine(user_id, vm_serializer_data, applications):
    """
    Initialize given virtual machine with selected application stored in database.
    @param user_id: id of caller.
    @param vm_serializer_data: serialized data contains information about virtual machines.
    @param applications: list of applications.
    @return:
    """
    is_timeout = False
    current_time = 0
    virtual_machine = VirtualMachine(user_id)
    while virtual_machine.get_vm_status(vm_serializer_data.get('vm_id')) != \
            [key for key, value in states.vm_states.iteritems() if value == 'running ctx'][0]:
        current_time += LOOP_TIME
        is_timeout = SSHConnector.timeout(WAIT_TIME, LOOP_TIME, current_time)
        if is_timeout:
            break

    if not is_timeout:
        # ssh = SSHConnector(virtual_machine.get_vm_private_ip(vm_serializer_data.get('vm_id')), ROOT,
        #                    SSH_KEY_PATH)
        #
        # ssh.exec_task(init_juju_on_vm)
        #
        # for application in ast.literal_eval(applications):
        #     app = Applications.objects.get(application_name=application)
        #     ssh.call_remote_command(app.instalation_procedure)
        ssh = RunCommand()
        ssh.do_add_host(virtual_machine.get_vm_private_ip(vm_serializer_data.get('vm_id')), ROOT,
                        VM_IMAGE_ROOT_PASSWORD)
        ssh.do_connect()
        ssh.do_run('juju generate-config && juju switch local && juju bootstrap')
    else:
        raise Exception

@app.task(trail=False, ignore_result=True, name='core.utils.tasks.destroy_virtual_machine')
@dev_cloud_task(DESTROY_VM)
def destroy_virtual_machine(user_id, vm_id):
    """
    Destroys the given virtual machine.
    @param user_id: id of caller.
    @param vm_id: id of virtual machine.
    @return: OK if machine is properly destroyed or FAILED if not.
    """
    current_time = 0
    virtual_machine = VirtualMachine(user_id)
    while virtual_machine.get_vm_status(vm_id) != \
            [key for key, value in states.vm_states.iteritems() if value == 'running ctx'][0]:
        current_time += LOOP_TIME
        is_timeout = SSHConnector.timeout(WAIT_TIME, LOOP_TIME, current_time)
        if is_timeout:
            break

    virtual_machine = VirtualMachine(user_id)
    return virtual_machine.destroy(vm_id)
<|endoftext|>


<commit_before>"""
The ``modelchain`` module contains functions and classes of the
windpowerlib. This module makes it easy to get started with the windpowerlib
and demonstrates standard ways to use the library.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import logging
import sys
from windpowerlib import wind_speed, density, power_output

class Modelchain(object):
    r"""Model to determine the output of a wind turbine

    Parameters
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'cp_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    hellman_z0 : float
        Roughness length. Default: None.

    Attributes
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'cp_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    hellman_z0 : float
        Roughness length. Default: None.
    power_output : pandas.Series
        Electrical power output of the wind turbine in W.

    Examples
    --------
    >>> from windpowerlib import modelchain
    >>> from windpowerlib import wind_turbine
    >>> enerconE126 = {
    ...    'hub_height': 135,
    ...    'd_rotor': 127,
    ...    'wind_conv_type': 'ENERCON E 126 7500'}
    >>> e126 = wind_turbine.WindTurbine(**enerconE126)
    >>> modelchain_data = {'rho_model': 'ideal_gas',
    ...    'temperature_model': 'interpolation'}
    >>> e126_md = modelchain.Modelchain(e126, **modelchain_data)
    >>> print(e126.d_rotor)
    127

    """

    def __init__(self, wind_turbine,
                 obstacle_height=0,
                 wind_model='logarithmic',
                 rho_model='barometric',
                 temperature_model='gradient',
                 power_output_model='cp_values',
                 density_corr=False,
                 hellman_exp=None,
                 hellman_z0=None):

        self.wind_turbine = wind_turbine
        self.obstacle_height = obstacle_height
        self.wind_model = wind_model
        self.rho_model = rho_model
        self.temperature_model = temperature_model
        self.power_output_model = power_output_model
        self.density_corr = density_corr
        self.hellman_exp = hellman_exp
        self.hellman_z0 = hellman_z0
        self.power_output = None

    def rho_hub(self, weather, data_height):
        r"""
        Calculates the density of air at hub height.

        The density is calculated using the method specified by the parameter
        `rho_model`. Previous to the calculation of density the temperature at
        hub height is calculated using the method specified by the parameter
        `temperature_model`.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with timeseries for temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally the temperature `temp_air_2` in K at a different height
            for interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        rho_hub : pandas.Series or array
            Density of air in kg/m³ at hub height.

        """
        # Check if temperature data is at hub height.
        if 'temp_air_2' not in weather:
            weather['temp_air_2'] = None
            data_height['temp_air_2'] = None
        if data_height['temp_air'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (at hub height).')
            T_hub = weather['temp_air']
        elif data_height['temp_air_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (2) (at hub height).')
            T_hub = weather['temp_air_2']
        # Calculation of temperature in K at hub height.
        elif self.temperature_model == 'gradient':
            logging.debug('Calculating temperature using a temp. gradient.')
            T_hub = density.temperature_gradient(
                weather['temp_air'], data_height['temp_air'],
                self.wind_turbine.hub_height)
        elif self.temperature_model == 'interpolation':
            logging.debug('Calculating temperature using interpolation.')
            T_hub = density.temperature_interpol(
                weather['temp_air'], weather['temp_air_2'],
                data_height['temp_air'], data_height['temp_air_2'],
                self.wind_turbine.hub_height)
        else:
            logging.info('Wrong value: `temperature_model` must be gradient ' +
                         'or interpolation.')
        # Calculation of density in kg/m³ at hub height
        if self.rho_model == 'barometric':
            logging.debug('Calculating density using barometric height eq.')
            rho_hub = density.rho_barometric(weather['pressure'],
                                             data_height['pressure'],
                                             self.wind_turbine.hub_height,
                                             T_hub)
        elif self.rho_model == 'ideal_gas':
            logging.debug('Calculating density using ideal gas equation.')
            rho_hub = density.rho_ideal_gas(weather['pressure'],
                                            data_height['pressure'],
                                            self.wind_turbine.hub_height,
                                            T_hub)
        else:
            logging.info('Wrong value: `rho_model` must be barometric ' +
                         'or ideal_gas.')
        return rho_hub

    def v_wind_hub(self, weather, data_height):
        r"""
        Calculates the wind speed at hub height.

        The method specified by the parameter `wind_model` is used.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s and roughness length `z0` in m, as well as
            optionally wind speed `v_wind_2` in m/s at different height for
            interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        v_wind : pandas.Series or array
            Wind speed in m/s at hub height.

        """
        # Check if wind speed data is at hub height.
        if 'v_wind_2' not in weather:
            weather['v_wind_2'] = None
            data_height['v_wind_2'] = None
        if data_height['v_wind'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (at hub height).')
            v_wind = weather['v_wind']
        elif data_height['v_wind_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (2) (at hub height).')
            v_wind = weather['v_wind_2']
        # Calculation of wind speed in m/s at hub height.
        elif self.wind_model == 'logarithmic':
            logging.debug('Calculating v_wind using logarithmic wind profile.')
            if weather['v_wind_2'] is None:
                v_wind = wind_speed.logarithmic_wind_profile(
                    weather['v_wind'], data_height['v_wind'],
                    self.wind_turbine.hub_height,
                    weather['z0'], self.obstacle_height)
            else:
                if (abs(data_height['v_wind'] -
                        self.wind_turbine.hub_height) <=
                        abs(data_height['v_wind_2'] -
                            self.wind_turbine.hub_height)):
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind'], data_height['v_wind'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
                else:
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind_2'], data_height['v_wind_2'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
        elif self.wind_model == 'hellman':
            logging.debug('Calculating v_wind using hellman equation.')
            v_wind = wind_speed.v_wind_hellman(
                weather['v_wind'], data_height['v_wind'],
                self.wind_turbine.hub_height,
                self.hellman_exp, self.hellman_z0)
        else:
            logging.error('Wrong value: `wind_model` must be logarithmic ' +
                          'or hellman.')
            sys.exit()
        return v_wind

    def turbine_power_output(self, v_wind, rho_hub):
        r"""
        Calculates the power output of the wind turbine.

        The method specified by the parameter `power_output_model` is used.

        Parameters
        ----------
        v_wind : pandas.Series or array
            Wind speed at hub height in m/s.
        rho_hub : pandas.Series or array
            Density of air at hub height in kg/m³.

        Returns
        -------
        output : pandas.Series
            Electrical power in W of the wind turbine.

        """
        if self.power_output_model == 'cp_values':
            if self.density_corr is False:
                logging.debug('Calculating power output using cp curve.')
                output = power_output.cp_curve(v_wind, rho_hub,
                                               self.wind_turbine.d_rotor,
                                               self.wind_turbine.cp_values)
            else:
                logging.debug('Calculating power output using density ' +
                              'corrected cp curve.')
                output = power_output.cp_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.d_rotor,
                    self.wind_turbine.cp_values)
        elif self.power_output_model == 'p_values':
            if self.density_corr is False:
                logging.debug('Calculating power output using power curve.')
                output = power_output.p_curve(self.wind_turbine.p_values,
                                              v_wind)
            else:
                logging.debug('Calculating power output using density ' +
                              'corrected power curve.')
                output = power_output.p_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.p_values)
        else:
            logging.info('Wrong value: `power_output_model` must be ' +
                         'cp_values or p_values.')
        return output

    def run_model(self, weather, data_height):
        r"""
        Runs the model.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s ,roughness length `z0` in m, temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally wind speed `v_wind_2` in m/s and temperature
            `temp_air_2` in K at different height for interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        self

        """
        v_wind = self.v_wind_hub(weather, data_height)
        rho_hub = self.rho_hub(weather, data_height)
        self.power_output = self.turbine_power_output(v_wind, rho_hub)
        return self
<commit_msg>Bug fix modelchain<commit_after>"""
The ``modelchain`` module contains functions and classes of the
windpowerlib. This module makes it easy to get started with the windpowerlib
and demonstrates standard ways to use the library.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import logging
import sys
from windpowerlib import wind_speed, density, power_output

class Modelchain(object):
    r"""Model to determine the output of a wind turbine

    Parameters
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'cp_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    hellman_z0 : float
        Roughness length. Default: None.

    Attributes
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'cp_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    hellman_z0 : float
        Roughness length. Default: None.
    power_output : pandas.Series
        Electrical power output of the wind turbine in W.

    Examples
    --------
    >>> from windpowerlib import modelchain
    >>> from windpowerlib import wind_turbine
    >>> enerconE126 = {
    ...    'hub_height': 135,
    ...    'd_rotor': 127,
    ...    'wind_conv_type': 'ENERCON E 126 7500'}
    >>> e126 = wind_turbine.WindTurbine(**enerconE126)
    >>> modelchain_data = {'rho_model': 'ideal_gas',
    ...    'temperature_model': 'interpolation'}
    >>> e126_md = modelchain.Modelchain(e126, **modelchain_data)
    >>> print(e126.d_rotor)
    127

    """

    def __init__(self, wind_turbine,
                 obstacle_height=0,
                 wind_model='logarithmic',
                 rho_model='barometric',
                 temperature_model='gradient',
                 power_output_model='cp_values',
                 density_corr=False,
                 hellman_exp=None,
                 hellman_z0=None):

        self.wind_turbine = wind_turbine
        self.obstacle_height = obstacle_height
        self.wind_model = wind_model
        self.rho_model = rho_model
        self.temperature_model = temperature_model
        self.power_output_model = power_output_model
        self.density_corr = density_corr
        self.hellman_exp = hellman_exp
        self.hellman_z0 = hellman_z0
        self.power_output = None

    def rho_hub(self, weather, data_height):
        r"""
        Calculates the density of air at hub height.

        The density is calculated using the method specified by the parameter
        `rho_model`. Previous to the calculation of density the temperature at
        hub height is calculated using the method specified by the parameter
        `temperature_model`.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with timeseries for temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally the temperature `temp_air_2` in K at a different height
            for interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        rho_hub : pandas.Series or array
            Density of air in kg/m³ at hub height.

        """
        # Check if temperature data is at hub height.
        if 'temp_air_2' not in weather:
            weather['temp_air_2'] = None
            data_height['temp_air_2'] = None
        if data_height['temp_air'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (at hub height).')
            T_hub = weather['temp_air']
        elif data_height['temp_air_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (2) (at hub height).')
            T_hub = weather['temp_air_2']
        # Calculation of temperature in K at hub height.
        elif self.temperature_model == 'gradient':
            logging.debug('Calculating temperature using a temp. gradient.')
            T_hub = density.temperature_gradient(
                weather['temp_air'], data_height['temp_air'],
                self.wind_turbine.hub_height)
        elif self.temperature_model == 'interpolation':
            logging.debug('Calculating temperature using interpolation.')
            T_hub = density.temperature_interpol(
                weather['temp_air'], weather['temp_air_2'],
                data_height['temp_air'], data_height['temp_air_2'],
                self.wind_turbine.hub_height)
        else:
            logging.info('Wrong value: `temperature_model` must be gradient ' +
                         'or interpolation.')
            sys.exit()
        # Calculation of density in kg/m³ at hub height
        if self.rho_model == 'barometric':
            logging.debug('Calculating density using barometric height eq.')
            rho_hub = density.rho_barometric(weather['pressure'],
                                             data_height['pressure'],
                                             self.wind_turbine.hub_height,
                                             T_hub)
        elif self.rho_model == 'ideal_gas':
            logging.debug('Calculating density using ideal gas equation.')
            rho_hub = density.rho_ideal_gas(weather['pressure'],
                                            data_height['pressure'],
                                            self.wind_turbine.hub_height,
                                            T_hub)
        else:
            logging.info('Wrong value: `rho_model` must be barometric ' +
                         'or ideal_gas.')
            sys.exit()
        return rho_hub

    def v_wind_hub(self, weather, data_height):
        r"""
        Calculates the wind speed at hub height.

        The method specified by the parameter `wind_model` is used.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s and roughness length `z0` in m, as well as
            optionally wind speed `v_wind_2` in m/s at different height for
            interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        v_wind : pandas.Series or array
            Wind speed in m/s at hub height.

        """
        # Check if wind speed data is at hub height.
        if 'v_wind_2' not in weather:
            weather['v_wind_2'] = None
            data_height['v_wind_2'] = None
        if data_height['v_wind'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (at hub height).')
            v_wind = weather['v_wind']
        elif data_height['v_wind_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (2) (at hub height).')
            v_wind = weather['v_wind_2']
        # Calculation of wind speed in m/s at hub height.
        elif self.wind_model == 'logarithmic':
            logging.debug('Calculating v_wind using logarithmic wind profile.')
            if weather['v_wind_2'].isnull().all():
                v_wind = wind_speed.logarithmic_wind_profile(
                    weather['v_wind'], data_height['v_wind'],
                    self.wind_turbine.hub_height,
                    weather['z0'], self.obstacle_height)
            else:
                if (abs(data_height['v_wind'] -
                        self.wind_turbine.hub_height) <=
                        abs(data_height['v_wind_2'] -
                            self.wind_turbine.hub_height)):
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind'], data_height['v_wind'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
                else:
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind_2'], data_height['v_wind_2'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
        elif self.wind_model == 'hellman':
            logging.debug('Calculating v_wind using hellman equation.')
            v_wind = wind_speed.v_wind_hellman(
                weather['v_wind'], data_height['v_wind'],
                self.wind_turbine.hub_height,
                self.hellman_exp, self.hellman_z0)
        else:
            logging.error('Wrong value: `wind_model` must be logarithmic ' +
                          'or hellman.')
            sys.exit()
        return v_wind

    def turbine_power_output(self, v_wind, rho_hub):
        r"""
        Calculates the power output of the wind turbine.

        The method specified by the parameter `power_output_model` is used.

        Parameters
        ----------
        v_wind : pandas.Series or array
            Wind speed at hub height in m/s.
        rho_hub : pandas.Series or array
            Density of air at hub height in kg/m³.

        Returns
        -------
        output : pandas.Series
            Electrical power in W of the wind turbine.

        """
        if self.power_output_model == 'cp_values':
            if self.density_corr is False:
                logging.debug('Calculating power output using cp curve.')
                output = power_output.cp_curve(v_wind, rho_hub,
                                               self.wind_turbine.d_rotor,
                                               self.wind_turbine.cp_values)
            else:
                logging.debug('Calculating power output using density ' +
                              'corrected cp curve.')
                output = power_output.cp_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.d_rotor,
                    self.wind_turbine.cp_values)
        elif self.power_output_model == 'p_values':
            if self.density_corr is False:
                logging.debug('Calculating power output using power curve.')
                output = power_output.p_curve(self.wind_turbine.p_values,
                                              v_wind)
            else:
                logging.debug('Calculating power output using density ' +
                              'corrected power curve.')
                output = power_output.p_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.p_values)
        else:
            logging.info('Wrong value: `power_output_model` must be ' +
                         'cp_values or p_values.')
        return output

    def run_model(self, weather, data_height):
        r"""
        Runs the model.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s ,roughness length `z0` in m, temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally wind speed `v_wind_2` in m/s and temperature
            `temp_air_2` in K at different height for interpolation.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        self

        """
        v_wind = self.v_wind_hub(weather, data_height)
        rho_hub = self.rho_hub(weather, data_height)
        self.power_output = self.turbine_power_output(v_wind, rho_hub)
        return self
<|endoftext|>


<commit_before>"""
The ``wind_speed`` module contains functions to calculate the wind speed at
hub height of a wind turbine.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import numpy as np

def logarithmic_wind_profile(v_wind, v_wind_height, hub_height, z_0,
                             obstacle_height=0):
    r"""
    Calculates the wind speed at hub height using a logarithmic wind profile.

    The logarithmic height equation is used. There is the possibility of
    including the height of the surrounding obstacles in the calculation. This
    function is carried out when the parameter `wind_model` of an instance of
    the :class:`~.modelchain.ModelChain` class is 'logarithmic' or
    'logarithmic_closest'.

    Parameters
    ----------
    v_wind : pandas.Series or array
        Wind speed time series.
    v_wind_height : float
        Height for which the parameter `v_wind` applies.
    hub_height : float
        Hub height of wind turbine.
    z_0 : pandas.Series or array or float
        Roughness length.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine. Set
        `obstacle_height` to zero for wide spread obstacles. Default: 0.

    Returns
    -------
    pandas.Series or array
        Wind speed at hub height.

    Notes
    -----
    The following equation is used [1]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot
        \frac{\ln\left(\frac{h_{hub}-d}{z_{0}}\right)}{\ln\left(
        \frac{h_{data}-d}{z_{0}}\right)}

    with:
        v: wind speed, h: height, :math:`z_{0}`: roughness length,
        d: boundary layer offset (estimated by d = 0.7 * `obstacle_height`)

    For  d = 0 it results in the following equation [2]_, [3]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot\frac{\ln\left(\frac{h_{hub}}
        {z_{0}}\right)}{\ln\left(\frac{h_{data}}{z_{0}}\right)}

    :math:`h_{data}` is the height at which the wind speed
    :math:`v_{wind,data}` is measured.

    Parameters `v_wind_height`, `z_0`, `hub_height` and `obstacle_height` have
    to be of the same unit.

    References
    ----------
    .. [1] Quaschning V.: "Regenerative Energiesysteme". München, Hanser
            Verlag, 2011, p. 278
    .. [2] Gasch, R., Twele, J.: "Windkraftanlagen". 6. Auflage, Wiesbaden,
            Vieweg + Teubner, 2010, p. 129
    .. [3] Hau, E.: "Windkraftanlagen - Grundlagen, Technik, Einsatz,
            Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 515

    """
    if 0.7 * obstacle_height > v_wind_height:
        raise ValueError("To take an obstacle height of {0} m".format(
                         obstacle_height) + " into consideration, wind" +
                         " speed data of a higher height is needed.")
    return (v_wind * np.log((hub_height - 0.7 * obstacle_height) / z_0) /
            np.log((v_wind_height - 0.7 * obstacle_height) / z_0))

def v_wind_hellman(v_wind, v_wind_height, hub_height, hellman_exp=None,
                   z_0=None):
    r"""
    Calculates the wind speed at hub height using the hellman equation.

    It is assumed that the wind profile follows a power law. This fuction is
    carried out when the parameter `wind_model` of an instance of
    the :class:`~.modelchain.ModelChain` class is 'hellman'.

    Parameters
    ----------
    v_wind : pandas.Series or array
        Wind speed time series.
    v_wind_height : float
        Height for which the parameter `v_wind` applies.
    hub_height : float
        Hub height of wind turbine.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None. If None and roughness length is given
        `hellman_exp` = 1 / ln(h_hub/z_0).
    z_0 : pandas.Series or array or float
        Roughness length. Default: None.

    Returns
    -------
    pandas.Series or array
        Wind speed at hub height.

    Notes
    -----
    The following equation is used [1]_,
    [2]_, [3]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot \left(\frac{h_{hub}}{h_{data}}
        \right)^\alpha

    with:
        v: wind speed, h: height, :math:`\alpha`: Hellman exponent

    :math:`h_{data}` is the height in which the wind speed
    :math:`v_{wind,data}` is measured and :math:`h_{hub}` is the hub height of
    the wind turbine.

    For the Hellman exponent :math:`\alpha` many studies use a value of 1/7 for
    onshore and a value of 1/9 for offshore. The Hellman exponent can also
    be calulated by the following equation [2]_, [3]_:

    .. math:: \alpha = \frac{1}{ln\left(\frac{h_{hub}}{z_0} \right)}

    with:
        :math:`z_{0}`: roughness length

    References
    ----------
    .. [1] Sharp, E.: "Spatiotemporal disaggregation of GB scenarios depicting
            increased wind capacity and electrified heat demand in dwellings".
            UCL, Energy Institute, 2015, p. 83
    .. [2] Hau, E.: "Windkraftanlagen - Grundlagen, Technik, Einsatz,
            Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 517
    .. [3] Quaschning V.: "Regenerative Energiesysteme". München, Hanser
            Verlag, 2011, p. 279

    """
    if hellman_exp is None:
        if z_0 is not None:
            hellman_exp = 1 / np.log(hub_height / z_0)
        else:
            hellman_exp = 1/7
    else:
        if not isinstance(hellman_exp, float):
            raise TypeError("'{0}' is an invalid type.".format(
                            type(hellman_exp)) +
                            "`hellman_exp` must be float.")
    return v_wind * (hub_height / v_wind_height) ** hellman_exp
<commit_msg>Add explanations to docstring of v_wind_hellman<commit_after>"""
The ``wind_speed`` module contains functions to calculate the wind speed at
hub height of a wind turbine.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import numpy as np

def logarithmic_wind_profile(v_wind, v_wind_height, hub_height, z_0,
                             obstacle_height=0):
    r"""
    Calculates the wind speed at hub height using a logarithmic wind profile.

    The logarithmic height equation is used. There is the possibility of
    including the height of the surrounding obstacles in the calculation. This
    function is carried out when the parameter `wind_model` of an instance of
    the :class:`~.modelchain.ModelChain` class is 'logarithmic' or
    'logarithmic_closest'.

    Parameters
    ----------
    v_wind : pandas.Series or array
        Wind speed time series.
    v_wind_height : float
        Height for which the parameter `v_wind` applies.
    hub_height : float
        Hub height of wind turbine.
    z_0 : pandas.Series or array or float
        Roughness length.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine. Set
        `obstacle_height` to zero for wide spread obstacles. Default: 0.

    Returns
    -------
    pandas.Series or array
        Wind speed at hub height.

    Notes
    -----
    The following equation is used [1]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot
        \frac{\ln\left(\frac{h_{hub}-d}{z_{0}}\right)}{\ln\left(
        \frac{h_{data}-d}{z_{0}}\right)}

    with:
        v: wind speed, h: height, :math:`z_{0}`: roughness length,
        d: boundary layer offset (estimated by d = 0.7 * `obstacle_height`)

    For  d = 0 it results in the following equation [2]_, [3]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot\frac{\ln\left(\frac{h_{hub}}
        {z_{0}}\right)}{\ln\left(\frac{h_{data}}{z_{0}}\right)}

    :math:`h_{data}` is the height at which the wind speed
    :math:`v_{wind,data}` is measured.

    Parameters `v_wind_height`, `z_0`, `hub_height` and `obstacle_height` have
    to be of the same unit.

    References
    ----------
    .. [1] Quaschning V.: "Regenerative Energiesysteme". München, Hanser
            Verlag, 2011, p. 278
    .. [2] Gasch, R., Twele, J.: "Windkraftanlagen". 6. Auflage, Wiesbaden,
            Vieweg + Teubner, 2010, p. 129
    .. [3] Hau, E.: "Windkraftanlagen - Grundlagen, Technik, Einsatz,
            Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 515

    """
    if 0.7 * obstacle_height > v_wind_height:
        raise ValueError("To take an obstacle height of {0} m".format(
                         obstacle_height) + " into consideration, wind" +
                         " speed data of a higher height is needed.")
    return (v_wind * np.log((hub_height - 0.7 * obstacle_height) / z_0) /
            np.log((v_wind_height - 0.7 * obstacle_height) / z_0))

def v_wind_hellman(v_wind, v_wind_height, hub_height, hellman_exp=None,
                   z_0=None):
    r"""
    Calculates the wind speed at hub height using the hellman equation.

    It is assumed that the wind profile follows a power law. This fuction is
    carried out when the parameter `wind_model` of an instance of
    the :class:`~.modelchain.ModelChain` class is 'hellman'.

    Parameters
    ----------
    v_wind : pandas.Series or array
        Wind speed time series.
    v_wind_height : float
        Height for which the parameter `v_wind` applies.
    hub_height : float
        Hub height of wind turbine.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None. If None and roughness length is given
        `hellman_exp` = 1 / ln(h_hub/z_0), otherwise `hellman_exp` = 1/7.
    z_0 : pandas.Series or array or float
        Roughness length. Default: None. If given
        `hellman_exp` = 1 / ln(h_hub/z_0), otherwise `hellman_exp` = 1/7.

    Returns
    -------
    pandas.Series or array
        Wind speed at hub height.

    Notes
    -----
    The following equation is used [1]_,
    [2]_, [3]_:

    .. math:: v_{wind,hub}=v_{wind,data}\cdot \left(\frac{h_{hub}}{h_{data}}
        \right)^\alpha

    with:
        v: wind speed, h: height, :math:`\alpha`: Hellman exponent

    :math:`h_{data}` is the height in which the wind speed
    :math:`v_{wind,data}` is measured and :math:`h_{hub}` is the hub height of
    the wind turbine.

    For the Hellman exponent :math:`\alpha` many studies use a value of 1/7 for
    onshore and a value of 1/9 for offshore. The Hellman exponent can also
    be calulated by the following equation [2]_, [3]_:

    .. math:: \alpha = \frac{1}{ln\left(\frac{h_{hub}}{z_0} \right)}

    with:
        :math:`z_{0}`: roughness length

    References
    ----------
    .. [1] Sharp, E.: "Spatiotemporal disaggregation of GB scenarios depicting
            increased wind capacity and electrified heat demand in dwellings".
            UCL, Energy Institute, 2015, p. 83
    .. [2] Hau, E.: "Windkraftanlagen - Grundlagen, Technik, Einsatz,
            Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 517
    .. [3] Quaschning V.: "Regenerative Energiesysteme". München, Hanser
            Verlag, 2011, p. 279

    """
    if hellman_exp is None:
        if z_0 is not None:
            hellman_exp = 1 / np.log(hub_height / z_0)
        else:
            hellman_exp = 1/7
    else:
        if not isinstance(hellman_exp, float):
            raise TypeError("'{0}' is an invalid type.".format(
                            type(hellman_exp)) +
                            "`hellman_exp` must be float.")
    return v_wind * (hub_height / v_wind_height) ** hellman_exp
<|endoftext|>


<commit_before>from tempfile import mkdtemp
from shutil import rmtree
import os
from ConfigParser import ConfigParser
from datetime import datetime

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.client import Client

from devilry.xmlrpc.testhelpers import get_serverproxy, XmlRpcAssertsMixin
from devilry.core.testhelpers import create_from_path
from devilry.core.models import Delivery, AssignmentGroup

from cookie_transport import CookieTransport, SafeCookieTransport
from command import Command
from utils import AssignmentSync, InfoFileDoesNotExistError, \
    InfoFileWrongTypeError, InfoFileMissingSectionError

import logging
logging.basicConfig(level=logging.ERROR)

class TestCommand(TestCase):
    def setUp(self):
        self.root = mkdtemp(prefix='devilry-test-')
        self.configdir = os.path.realpath(
                os.path.join(self.root, '.devilry'))
        self.oldcwd = os.getcwd()
        os.chdir(self.root)
        os.mkdir(self.configdir)

        self.ob1dir = os.path.join(self.configdir, 'ifi.inf1100', 'oblig1')
        os.makedirs(self.ob1dir)
        open(os.path.join(self.ob1dir, '.assignment-id'), 'w').write('20')

        class TestCommand(Command):
            urlpath = '/xmlrpc/'
        self.cmd = TestCommand()

    def tearDown(self):
        os.chdir(self.oldcwd)
        rmtree(self.root)

    def test_get_rootdir(self):
        self.assertTrue(os.path.samefile(self.root,
            self.cmd.get_rootdir()))

    def test_config(self):
        self.assertTrue(os.path.samefile(self.configdir,
            self.cmd.get_configdir()))
        self.cmd.set_config('hello', 'world')
        self.assertEquals('world', self.cmd.get_config('hello'))
        self.cmd.set_config('url', 'http://test')
        self.assertEquals('world', self.cmd.get_config('hello'))
        self.cmd.write_config()
        cfgfile = os.path.join(self.configdir, 'config.cfg')
        cfg = ConfigParser()
        cfg.read([cfgfile])
        self.assertEquals(cfg.get('settings', 'hello'), 'world')

    def test_get_id_from_path(self):
        self.assertEquals(20,
                self.cmd.get_id_from_path(self.ob1dir, '.assignment-id'))

    def test_determine_id(self):
        self.assertEquals(10,
                self.cmd.determine_id('10', '.assignment-id'))
        self.assertEquals(20,
                self.cmd.determine_id(self.ob1dir, '.assignment-id'))

    def test_get_cookiepath(self):
        self.assertEquals(os.path.join(self.configdir, 'cookies.txt'),
                self.cmd.get_cookiepath())

    def test_get_serverproxy(self):
        self.cmd.set_config('url', 'http://test')
        serverproxy = self.cmd.get_serverproxy()._ServerProxy__transport
        self.assertTrue(isinstance(serverproxy, CookieTransport))
        self.cmd.set_config('url', 'https://test')
        serverproxy = self.cmd.get_serverproxy()._ServerProxy__transport
        self.assertTrue(isinstance(serverproxy, SafeCookieTransport))

class TestAssignmentSyncBase(TestCase, XmlRpcAssertsMixin):
    fixtures = ['tests/xmlrpc_examiner/users',
            'tests/xmlrpc_examiner/core']

    def sync(self):
        return AssignmentSync(
                self.root,
                os.path.join(self.root, 'cookie.txt'),
                self.server, 'http://test')

    def setUp(self):
        self.client = Client()
        self.server = get_serverproxy(self.client, '/xmlrpc_examiner/')
        self.login(self.client, 'examiner1')
        self.root = mkdtemp('devilry-test')
        self.sync()
        self.examiner1 = User.objects.get(username='examiner1')
        self.student2 = User.objects.get(username='student2')

    def tearDown(self):
        self.logout(self.client)
        rmtree(self.root)

class TestAssignmentSync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentSync, self).setUp()
        self.infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')

    def test_sync(self):
        self.assertEquals(os.listdir(self.root), ['inf1100.looong.oblig1'])
        assignmentgroup = create_from_path(
                'ifi:inf1010.spring09.oblig1.student1')
        assignmentgroup.examiners.add(self.examiner1)
        assignmentgroup.save()
        self.sync()
        dircontent = os.listdir(self.root)
        dircontent.sort()
        self.assertEquals(dircontent,
                ['inf1010.spring09.oblig1', 'inf1100.looong.oblig1'])
        info = ConfigParser() # Sanity test of info-file
        info.read([self.infofile])
        self.assertEquals(
                info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(info.get('info', 'id'), '1')

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(
                info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(info.get('info', 'id'), '1')
        self.assertEquals(info.get('info', 'short_name'), 'oblig1')
        self.assertEquals(
                info.get('info', 'long_name'), 'Obligatory assignment one')
        self.assertEquals(info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(
                info.get('info', 'publishing_time'), '2010-06-05 00:31:42')

    def test_assignment_missing_infofile(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        os.remove(infofile)
        self.assertRaises(InfoFileDoesNotExistError, self.sync)

    def test_assignment_infofile_missing_section(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        i = open(infofile, 'rb').read().replace('[info]', '[somethingelse]')
        open(infofile, 'wb').write(i)
        self.assertRaises(InfoFileMissingSectionError, self.sync)

    def test_assignment_infofile_wrongtype(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        i = open(infofile, 'rb').read().replace('type = Assignment',
                'type = somethingelse')
        open(infofile, 'wb').write(i)
        self.assertRaises(InfoFileWrongTypeError, self.sync)

class TestAssignmentGroupSync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentGroupSync, self).setUp()
        self.infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                'student2-student3', '.info')
        self.folder = os.path.join(self.root, 'inf1100.looong.oblig1')

    def test_sync(self):
        l = os.listdir(self.folder)
        l.sort()
        self.assertEquals(l, ['.info', 'student1', 'student2-student3'])

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(info.get('info', 'id'), '2')
        self.assertEquals(info.get('info', 'name'), '')
        self.assertEquals(
                info.get('info', 'students'), 'student2, student3')
        self.assertEquals(
                info.get('info', 'number_of_deliveries'), '1')

    def test_namecrash(self):
        assignmentgroup = create_from_path(
                'uio.ifi:inf1100.looong.oblig1.student2,student3')
        assignmentgroup.examiners.add(self.examiner1)
        assignmentgroup.save()
        delivery = Delivery.begin(assignmentgroup, self.student2)
        delivery.finish()
        self.sync()
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', 'student1', 'student2-student3.2',
            join_dirname_id('student2-student3', assignmentgroup.id)])

        # Make sure it works when id-based names are in the fs
        self.sync()
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', 'student1', 'student2-student3.2',
            join_dirname_id('student2-student3', assignmentgroup.id)])

class TestAssignmentDeliverySync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentDeliverySync, self).setUp()
        self.agfolder = os.path.join(self.root, 'inf1100.looong.oblig1',
                'student1')
        self.folder = os.path.join(self.agfolder, '2010-06-19_14.47.29')
        self.infofile = os.path.join(self.folder, '.info')

    def test_sync(self):
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent, ['.info', 'files'])
        agdircontent = os.listdir(self.agfolder)
        agdircontent.sort()
        self.assertEquals(agdircontent, ['.info', '2010-06-19_14.47.29'])

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(info.get('info', 'id'), '1')
        self.assertEquals(info.get('info', 'time_of_delivery'),
                '2010-06-19 14:47:29')

    def test_namecrash(self):
        assignmentgroup = AssignmentGroup.objects.get(id=1)
        delivery = Delivery.begin(assignmentgroup, self.student2)
        delivery.finish()
        delivery.time_of_delivery = datetime(2010, 6, 19, 14, 47, 29)
        delivery.save()
        self.sync()

        dircontent = os.listdir(self.agfolder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', '2010-06-19_14.47.29.1',
            join_dirname_id('2010-06-19_14.47.29', delivery.id)])

        # Make sure it works when id-based names are in the fs
        self.sync()
        dircontent = os.listdir(self.agfolder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', '2010-06-19_14.47.29.1',
                '2010-06-19_14.47.29.%s' % delivery.id])

    def test_feedback(self):
        delivery = Delivery.objects.get(id=1)
        f = delivery.get_feedback()
        f.feedback_text = 'test'
        f.feedback_published = True
        f.set_grade_from_string('+')
        f.save()
        self.sync()

# WARNING: We are have no tests for filemeta, because all the other tests
# use the django test-client, and it does not support file-downloads using
# urllib2.

<commit_msg>Updated the xmlrpc client tests with + as id-sep.<commit_after>from tempfile import mkdtemp
from shutil import rmtree
import os
from ConfigParser import ConfigParser
from datetime import datetime

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.client import Client

from devilry.xmlrpc.testhelpers import get_serverproxy, XmlRpcAssertsMixin
from devilry.core.testhelpers import create_from_path
from devilry.core.models import Delivery, AssignmentGroup

from cookie_transport import CookieTransport, SafeCookieTransport
from command import Command
from utils import AssignmentSync, InfoFileDoesNotExistError, \
    InfoFileWrongTypeError, InfoFileMissingSectionError, \
    join_dirname_id

import logging
logging.basicConfig(level=logging.ERROR)

class TestCommand(TestCase):
    def setUp(self):
        self.root = mkdtemp(prefix='devilry-test-')
        self.configdir = os.path.realpath(
                os.path.join(self.root, '.devilry'))
        self.oldcwd = os.getcwd()
        os.chdir(self.root)
        os.mkdir(self.configdir)

        self.ob1dir = os.path.join(self.configdir, 'ifi.inf1100', 'oblig1')
        os.makedirs(self.ob1dir)
        open(os.path.join(self.ob1dir, '.assignment-id'), 'w').write('20')

        class TestCommand(Command):
            urlpath = '/xmlrpc/'
        self.cmd = TestCommand()

    def tearDown(self):
        os.chdir(self.oldcwd)
        rmtree(self.root)

    def test_get_rootdir(self):
        self.assertTrue(os.path.samefile(self.root,
            self.cmd.get_rootdir()))

    def test_config(self):
        self.assertTrue(os.path.samefile(self.configdir,
            self.cmd.get_configdir()))
        self.cmd.set_config('hello', 'world')
        self.assertEquals('world', self.cmd.get_config('hello'))
        self.cmd.set_config('url', 'http://test')
        self.assertEquals('world', self.cmd.get_config('hello'))
        self.cmd.write_config()
        cfgfile = os.path.join(self.configdir, 'config.cfg')
        cfg = ConfigParser()
        cfg.read([cfgfile])
        self.assertEquals(cfg.get('settings', 'hello'), 'world')

    def test_get_id_from_path(self):
        self.assertEquals(20,
                self.cmd.get_id_from_path(self.ob1dir, '.assignment-id'))

    def test_determine_id(self):
        self.assertEquals(10,
                self.cmd.determine_id('10', '.assignment-id'))
        self.assertEquals(20,
                self.cmd.determine_id(self.ob1dir, '.assignment-id'))

    def test_get_cookiepath(self):
        self.assertEquals(os.path.join(self.configdir, 'cookies.txt'),
                self.cmd.get_cookiepath())

    def test_get_serverproxy(self):
        self.cmd.set_config('url', 'http://test')
        serverproxy = self.cmd.get_serverproxy()._ServerProxy__transport
        self.assertTrue(isinstance(serverproxy, CookieTransport))
        self.cmd.set_config('url', 'https://test')
        serverproxy = self.cmd.get_serverproxy()._ServerProxy__transport
        self.assertTrue(isinstance(serverproxy, SafeCookieTransport))

class TestAssignmentSyncBase(TestCase, XmlRpcAssertsMixin):
    fixtures = ['tests/xmlrpc_examiner/users',
            'tests/xmlrpc_examiner/core']

    def sync(self):
        return AssignmentSync(
                self.root,
                os.path.join(self.root, 'cookie.txt'),
                self.server, 'http://test')

    def setUp(self):
        self.client = Client()
        self.server = get_serverproxy(self.client, '/xmlrpc_examiner/')
        self.login(self.client, 'examiner1')
        self.root = mkdtemp('devilry-test')
        self.sync()
        self.examiner1 = User.objects.get(username='examiner1')
        self.student2 = User.objects.get(username='student2')

    def tearDown(self):
        self.logout(self.client)
        rmtree(self.root)

class TestAssignmentSync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentSync, self).setUp()
        self.infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')

    def test_sync(self):
        self.assertEquals(os.listdir(self.root), ['inf1100.looong.oblig1'])
        assignmentgroup = create_from_path(
                'ifi:inf1010.spring09.oblig1.student1')
        assignmentgroup.examiners.add(self.examiner1)
        assignmentgroup.save()
        self.sync()
        dircontent = os.listdir(self.root)
        dircontent.sort()
        self.assertEquals(dircontent,
                ['inf1010.spring09.oblig1', 'inf1100.looong.oblig1'])
        info = ConfigParser() # Sanity test of info-file
        info.read([self.infofile])
        self.assertEquals(
                info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(info.get('info', 'id'), '1')

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(
                info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(info.get('info', 'id'), '1')
        self.assertEquals(info.get('info', 'short_name'), 'oblig1')
        self.assertEquals(
                info.get('info', 'long_name'), 'Obligatory assignment one')
        self.assertEquals(info.get('info', 'path'), 'inf1100.looong.oblig1')
        self.assertEquals(
                info.get('info', 'publishing_time'), '2010-06-05 00:31:42')

    def test_assignment_missing_infofile(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        os.remove(infofile)
        self.assertRaises(InfoFileDoesNotExistError, self.sync)

    def test_assignment_infofile_missing_section(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        i = open(infofile, 'rb').read().replace('[info]', '[somethingelse]')
        open(infofile, 'wb').write(i)
        self.assertRaises(InfoFileMissingSectionError, self.sync)

    def test_assignment_infofile_wrongtype(self):
        infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                '.info')
        i = open(infofile, 'rb').read().replace('type = Assignment',
                'type = somethingelse')
        open(infofile, 'wb').write(i)
        self.assertRaises(InfoFileWrongTypeError, self.sync)

class TestAssignmentGroupSync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentGroupSync, self).setUp()
        self.infofile = os.path.join(self.root, 'inf1100.looong.oblig1',
                'student2-student3', '.info')
        self.folder = os.path.join(self.root, 'inf1100.looong.oblig1')

    def test_sync(self):
        l = os.listdir(self.folder)
        l.sort()
        self.assertEquals(l, ['.info', 'student1', 'student2-student3'])

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(info.get('info', 'id'), '2')
        self.assertEquals(info.get('info', 'name'), '')
        self.assertEquals(
                info.get('info', 'students'), 'student2, student3')
        self.assertEquals(
                info.get('info', 'number_of_deliveries'), '1')

    def test_namecrash(self):
        assignmentgroup = create_from_path(
                'uio.ifi:inf1100.looong.oblig1.student2,student3')
        assignmentgroup.examiners.add(self.examiner1)
        assignmentgroup.save()
        delivery = Delivery.begin(assignmentgroup, self.student2)
        delivery.finish()
        self.sync()
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', 'student1', 'student2-student3+2',
            join_dirname_id('student2-student3', assignmentgroup.id)])

        # Make sure it works when id-based names are in the fs
        self.sync()
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', 'student1', 'student2-student3+2',
            join_dirname_id('student2-student3', assignmentgroup.id)])

class TestAssignmentDeliverySync(TestAssignmentSyncBase):
    def setUp(self):
        super(TestAssignmentDeliverySync, self).setUp()
        self.agfolder = os.path.join(self.root, 'inf1100.looong.oblig1',
                'student1')
        self.folder = os.path.join(self.agfolder, '2010-06-19_14.47.29')
        self.infofile = os.path.join(self.folder, '.info')

    def test_sync(self):
        dircontent = os.listdir(self.folder)
        dircontent.sort()
        self.assertEquals(dircontent, ['.info', 'files'])
        agdircontent = os.listdir(self.agfolder)
        agdircontent.sort()
        self.assertEquals(agdircontent, ['.info', '2010-06-19_14.47.29'])

    def test_infofile(self):
        self.assertTrue(os.path.isfile(self.infofile))
        info = ConfigParser()
        info.read([self.infofile])
        self.assertEquals(info.get('info', 'id'), '1')
        self.assertEquals(info.get('info', 'time_of_delivery'),
                '2010-06-19 14:47:29')

    def test_namecrash(self):
        assignmentgroup = AssignmentGroup.objects.get(id=1)
        delivery = Delivery.begin(assignmentgroup, self.student2)
        delivery.finish()
        delivery.time_of_delivery = datetime(2010, 6, 19, 14, 47, 29)
        delivery.save()
        self.sync()

        dircontent = os.listdir(self.agfolder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', '2010-06-19_14.47.29+1',
            join_dirname_id('2010-06-19_14.47.29', delivery.id)])

        # Make sure it works when id-based names are in the fs
        self.sync()
        dircontent = os.listdir(self.agfolder)
        dircontent.sort()
        self.assertEquals(dircontent,
            ['.info', '2010-06-19_14.47.29+1',
                join_dirname_id('2010-06-19_14.47.29', delivery.id)])

    def test_feedback(self):
        delivery = Delivery.objects.get(id=1)
        f = delivery.get_feedback()
        f.feedback_text = 'test'
        f.feedback_published = True
        f.set_grade_from_string('+')
        f.save()
        self.sync()

# WARNING: We are have no tests for filemeta, because all the other tests
# use the django test-client, and it does not support file-downloads using
# urllib2.

<|endoftext|>