<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

class CachedItems(object):
    """
    Abstract implementation for a caching collection of client names or ids.

    :param client: Client object.
    :type client: docker.client.Client
    """
    def __init__(self, client):
        self._client = client
        super(CachedItems, self).__init__()
        self.refresh()

    def refresh(self):
        """
        Forces a refresh of the cached items. Does not need to return anything.
        """
        raise NotImplementedError("Method 'refresh' is not implemented.")

class CachedImages(CachedItems, dict):
    """
    Dictionary of image names and ids, which also keeps track of the client object to pull images if necessary.
    """
    def __init__(self, *args, **kwargs):
        self._updated = set()
        super(CachedImages, self).__init__(*args, **kwargs)

    def refresh(self):
        """
        Fetches image and their ids from the client.
        """
        current_images = self._client.images()
        self.clear()
        for image in current_images:
            tags = image.get('RepoTags')
            if tags:
                self.update({tag: image['Id'] for tag in tags})

    def reset_updated(self):
        """
        Resets the cache which images have been pulled (i.e. updated on the default tag.)
        """
        self._updated = set()

    def ensure_image(self, image_name, pull=False, insecure_registry=False):
        """
        Ensures that a particular image is present on the client. If it is not, a new copy is pulled from the server.

        :param image_name: Image name. If it does not include a specific tag, ``latest`` is assumed.
        :type image_name: unicode | str
        :param pull: If the image includes a tag, pull it from the server even if it exists. This is is done only once
          in for the lifecycle of the cache, or unless `:meth:reset_updated` is called.
        :type pull: bool
        :param insecure_registry: Pull from an insecure registry where necessary.
        :type insecure_registry: bool
        :return: Image id associated with the image name.
        :rtype: unicode | str
        """
        image, __, tag = image_name.rpartition(':')
        if image:
            full_name = image_name
        else:
            full_name = '{0}:latest'.format(image_name)
            image = image_name
            tag = 'latest'
        if (pull and full_name not in self._updated) or full_name not in self:
            self._client.pull(repository=image, tag=tag, insecure_registry=insecure_registry)
            images = self._client.images(name=image_name)
            for new_image in images:
                tags = new_image.get('RepoTags')
                if tags:
                    self._updated.update(tags)
                    self.update({tag: new_image['Id'] for tag in tags})
        try:
            return self[full_name]
        except KeyError:
            raise KeyError("Image '{0}' not found.".format(full_name))

class CachedContainerNames(CachedItems, set):
    def refresh(self):
        """
        Fetches all current container names from the client.
        """
        current_containers = self._client.containers(all=True)
        self.clear()
        for container in current_containers:
            container_names = container.get('Names')
            if container_names:
                self.update(name[1:] for name in container_names)

class DockerHostItemCache(dict):
    """
    Abstract class for implementing caches of items (containers, images) present on the Docker client, so that
    their existence does not have to be checked separately for every action.

    :param clients: Dictionary of clients with alias and client object.
    :type clients: dict[unicode | str, dockermap.map.config.ClientConfiguration]
    """
    item_class = None

    def __init__(self, clients, *args, **kwargs):
        self._clients = clients
        super(DockerHostItemCache, self).__init__(*args, **kwargs)

    def __getitem__(self, item):
        """
        Retrieves the items associated with the given client. Returned results are cached for later use.

        :param item: Client name.
        :type item: unicode | str
        :return: Items in the cache.
        """
        if item not in self:
            return self.refresh(item)
        return super(DockerHostItemCache, self).__getitem__(item)

    def refresh(self, item):
        """
        Forces a refresh of a cached item.

        :param item: Client name.
        :type item: unicode | str
        :return: Items in the cache.
        :rtype: DockerHostItemCache.item_class
        """
        client = self._clients[item].get_client()
        val = self.item_class(client)
        self[item] = val
        return val

class ImageCache(DockerHostItemCache):
    """
    Fetches and caches image names and ids from a Docker host.
    """
    item_class = CachedImages

class ContainerCache(DockerHostItemCache):
    """
    Fetches and caches container names from a Docker host.
    """
    item_class = CachedContainerNames
<commit_msg>Fixed image cache update on specific tags.<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

class CachedItems(object):
    """
    Abstract implementation for a caching collection of client names or ids.

    :param client: Client object.
    :type client: docker.client.Client
    """
    def __init__(self, client):
        self._client = client
        super(CachedItems, self).__init__()
        self.refresh()

    def refresh(self):
        """
        Forces a refresh of the cached items. Does not need to return anything.
        """
        raise NotImplementedError("Method 'refresh' is not implemented.")

class CachedImages(CachedItems, dict):
    """
    Dictionary of image names and ids, which also keeps track of the client object to pull images if necessary.
    """
    def __init__(self, *args, **kwargs):
        self._updated = set()
        super(CachedImages, self).__init__(*args, **kwargs)

    def refresh(self):
        """
        Fetches image and their ids from the client.
        """
        current_images = self._client.images()
        self.clear()
        for image in current_images:
            tags = image.get('RepoTags')
            if tags:
                self.update({tag: image['Id'] for tag in tags})

    def reset_updated(self):
        """
        Resets the cache which images have been pulled (i.e. updated on the default tag.)
        """
        self._updated = set()

    def ensure_image(self, image_name, pull=False, insecure_registry=False):
        """
        Ensures that a particular image is present on the client. If it is not, a new copy is pulled from the server.

        :param image_name: Image name. If it does not include a specific tag, ``latest`` is assumed.
        :type image_name: unicode | str
        :param pull: If the image includes a tag, pull it from the server even if it exists. This is is done only once
          in for the lifecycle of the cache, or unless `:meth:reset_updated` is called.
        :type pull: bool
        :param insecure_registry: Pull from an insecure registry where necessary.
        :type insecure_registry: bool
        :return: Image id associated with the image name.
        :rtype: unicode | str
        """
        image, __, tag = image_name.rpartition(':')
        if image:
            full_name = image_name
        else:
            full_name = '{0}:latest'.format(image_name)
            image = image_name
            tag = 'latest'
        if (pull and full_name not in self._updated) or full_name not in self:
            self._client.pull(repository=image, tag=tag, insecure_registry=insecure_registry)
            images = self._client.images(name=image)
            for new_image in images:
                tags = new_image.get('RepoTags')
                if tags:
                    self._updated.update(tags)
                    self.update({tag: new_image['Id'] for tag in tags})
        try:
            return self[full_name]
        except KeyError:
            raise KeyError("Image not found.", full_name)

class CachedContainerNames(CachedItems, set):
    def refresh(self):
        """
        Fetches all current container names from the client.
        """
        current_containers = self._client.containers(all=True)
        self.clear()
        for container in current_containers:
            container_names = container.get('Names')
            if container_names:
                self.update(name[1:] for name in container_names)

class DockerHostItemCache(dict):
    """
    Abstract class for implementing caches of items (containers, images) present on the Docker client, so that
    their existence does not have to be checked separately for every action.

    :param clients: Dictionary of clients with alias and client object.
    :type clients: dict[unicode | str, dockermap.map.config.ClientConfiguration]
    """
    item_class = None

    def __init__(self, clients, *args, **kwargs):
        self._clients = clients
        super(DockerHostItemCache, self).__init__(*args, **kwargs)

    def __getitem__(self, item):
        """
        Retrieves the items associated with the given client. Returned results are cached for later use.

        :param item: Client name.
        :type item: unicode | str
        :return: Items in the cache.
        """
        if item not in self:
            return self.refresh(item)
        return super(DockerHostItemCache, self).__getitem__(item)

    def refresh(self, item):
        """
        Forces a refresh of a cached item.

        :param item: Client name.
        :type item: unicode | str
        :return: Items in the cache.
        :rtype: DockerHostItemCache.item_class
        """
        client = self._clients[item].get_client()
        val = self.item_class(client)
        self[item] = val
        return val

class ImageCache(DockerHostItemCache):
    """
    Fetches and caches image names and ids from a Docker host.
    """
    item_class = CachedImages

class ContainerCache(DockerHostItemCache):
    """
    Fetches and caches container names from a Docker host.
    """
    item_class = CachedContainerNames
<|endoftext|>


<commit_before>import io
import syntax
import persistant

def Dummy(data_type):
    class _Dummy(data_type,
            # persistant.Volatile,
            # io.Readable,
            io.Writable):
        def set_value(self, t, value):
            print t, value
            return True
    return _Dummy

Alarm = Dummy(syntax.Boolean)
Door = Dummy(syntax.Boolean)
ElectricCurrent = Dummy(syntax.Boolean)
Fan = Dummy(syntax.Boolean)
Gaz = Dummy(syntax.Boolean) #true = ouvert, flase = ferme
LightButton = Dummy(syntax.Boolean)
Piston = Dummy(syntax.Boolean)
Shutter = Dummy(syntax.Numeric)
Temperature = Dummy(syntax.Numeric)
WaterValve = Dummy(syntax.Boolean)
Window = Dummy(syntax.Boolean)

import sys
import string
from twisted.internet import protocol
from twisted.python.log import startLogging
from twisted.internet import reactor
from twisted.internet.protocol import ClientCreator
from twisted.internet.protocol import ClientFactory
from twisted.internet.protocol import Protocol
from twisted.internet.endpoints import TCP4ClientEndpoint

class Actuator(object):
    from twisted.internet import reactor
    #host = '134.214.106.23'
    #port = 5000
    host = '134.214.106.23'
    port = 5000
    actuator_id = ""
    org =""
    sentData=""
    connector=""

    def __init__(self):
        super(Actuator, self).__init__()
        # reactor.connectTCP(type(self).host,
        #         type(self).port,
        #         ActuatorConnectionFactory(self,
        #             type(self).actuator_id))
        point =    TCP4ClientEndpoint(reactor,self.host,self.port)
        self.deferred = point.connect(ActuatorConnectionFactory(self,self.actuator_id))

    def sendData(self,data):
        pass

    def start(self):
        self.connector = reactor.run()
        #super(Actuator, self).start()

    def close(self):
        self.connector.disconnect()
        #protocol.transport.loseConnection()
        #reactor.stop()
        super(Actuator, self).close()

class ActuatorConnection(Protocol):
    def __init__(self, actuator):
        self.actuator = actuator

    def connectionMade(self):
        print "Connexion etablished"
        self.transport.write(self.actuator.sentData)
        #self.transport.loseConnection()
        #reactor.callLater(1, self.actuator.deferred.cancel)
        self.actuator.deferred.cancel
        # reactor.stop()
        #self.transport.write(self.actuator.sentData)

    def dataReceived(self, data):
        pass
    def sendData(self):
        self.transport.write(self.actuator.sentData)

    def connectionLost(self, reason):
        print "connection lost"

class ActuatorConnectionFactory(ClientFactory):
    def __init__(self, actuator,filter_id):
        self.actuator = actuator
        self.filter_id = filter_id

    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"

    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"

    def buildProtocol(self, addr):
        return ActuatorConnection(self.actuator)

class PriseElectrique(Actuator):
    actuator_id = "FF9F1E02"
    #actuator_id = "FF9F1E03"
    org = "05"

    def sendData(self,data):
        stat_check = "308E"
        if data=="1": #activer
            data = "50000000"
        else:
            data = "70000000"
        self.sentData = "A55A6B"+self.org+data+self.actuator_id+stat_check
        self.start()
        #self.stop()

if __name__ == '__main__':
   a = PriseElectrique()
   a.sendData("1")
<commit_msg>Franck je t'ai dit de la merde<commit_after>import sys
import logging
import socket

import io
import syntax
import persistant

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
_formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
_handler = logging.StreamHandler()
_handler.setFormatter(_formatter)
_handler.setLevel(logging.DEBUG)
logger.addHandler(_handler)

def Dummy(data_type):
    class _Dummy(data_type, persistant.Volatile, io.Readable):
        def set_value(self, t, value):
            print t, value
    return _Dummy

Alarm = Dummy(syntax.Boolean)
Door = Dummy(syntax.Boolean)
ElectricCurrent = Dummy(syntax.Boolean)
Fan = Dummy(syntax.Boolean)
Gaz = Dummy(syntax.Boolean) #true = ouvert, flase = ferme
LightButton = Dummy(syntax.Boolean)
Piston = Dummy(syntax.Boolean)
Shutter = Dummy(syntax.Percentage)
Temperature = Dummy(syntax.Numeric)
WaterValve = Dummy(syntax.Boolean)
Window = Dummy(syntax.Boolean)

class Actuator(object):
    host = '134.214.106.23'
    port = 5000

    def __init__(self):
        super(Actuator, self).__init__()
        self.actuator_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.actuator_socket.connect((type(self).host, type(self).port))
        self.actuator_socket_file = self.actuator_socket.makefile()

    def set_value(self, t, value):
        """
        Start the actuator (eg. start sending via the reactor).
        """
        logger.info('setting the value to %s', value)
        data = self.prepare_data(value)
        self.actuator_socket_file.write(data)
        self.actuator_socket_file.flush()
        return super(Actuator, self).set_value(t, value)

    def close(self):
        """
        Close/stop the actuator.
        """
        logger.info('closing the connection')
        self.actuator_socket_file.close()

    def prepare_data(self, data):
        """
        Format data to send to the actuator, depending on its needed format.
        """
        raise NotImplementedError

class PowerPlug(Actuator, io.Writable):
    actuator_id = 'FF9F1E07'
    org = '05'

    def prepare_data(self, data):
        data = '50000000' if data else  '70000000'
        return ''.join(('A55A6B', type(self).org, data,
            type(self).actuator_id, '308E'))
<|endoftext|>


<commit_before>
"""
Rickie Kerndt <rkerndt@cs.uoregon.edu
bike_power_center.py
Provides services for monitoring and managing bicycle electrical systems
"""

from __future__ import print_function
import sys
sys.path.append('/home/pi/lib/python')

import signal
import ina219
import power_meter as pm
import rgb
from threading import Event, Timer
from datetime import datetime
import smbus

class PowerCenter():
    """
    Methods for monitoring power generating, consumption, and modifying on bicycle electronics to control
    power consumption.
    """

    CHARGING    = 0
    FULL_CHARGE = 1
    ON_BATTERY  = 2
    LOW_BATTERY = 3
    LOW_BATTERY_VOLTS = 3.2

    LOG_FILE = "/var/log/power_center.log"
    RUNNING = 0
    SHUTDOWN = 1
    TERMINATE = 2

    # timer intervals
    CHECK_BATTERY_INTERVAL = 1.0
    LOG_DATA_INTERVAL = 1.0
    POWER_MONITOR_INTERVAL = 0.08

    DEBUG = False

    # avr constants
    AVR_I2C_BUS = 1
    AVR_I2C_ADDRESS = 0x21
    AVR_BATT_CHRG_REG = 23

    def __init__(self):
        """
        Instantiates power center which for now just monitors battery and external power ina219 devices.
        """
        self._trigger = Event()
        self._state = None
        self.battery_power = pm.PowerMeter(pm.INA219_Monitor(0.1, 0x40, 1, ina219.INA219_CALIB_32V_1A, 128),
                                           self._trigger)
        self.dyno_power = pm.PowerMeter(pm.INA219_Monitor(0.1, 0x41, 1, ina219.INA219_CALIB_32V_2A, 128),
                                        self._trigger)
        self.log_file = PowerCenter.LOG_FILE
        self.log_fh = None
        self.battery_status = None
        self.battery_status_led = rgb.RGB_led(21, 20, 16)
        self._battery_timer = Timer(PowerCenter.CHECK_BATTERY_INTERVAL, self._check_battery)
        self._log_timer = None
        self._power_monitor_timer = Timer(PowerCenter.POWER_MONITOR_INTERVAL, self._power_monitor_sync)
        self._debug = PowerCenter.DEBUG
        self._i2c_bus = smbus.SMBus(PowerCenter.AVR_I2C_BUS)

        signal.signal(signal.SIGTERM, self._sig_handler)
        signal.signal(signal.SIGINT, self._sig_handler)
        signal.signal(signal.SIGUSR1, self._sig_handler)

    def run(self):
        """
        Starts things up and launches timers
        """
        self._state = PowerCenter.RUNNING
        self.battery_power.open()
        self.dyno_power.open()
        self._power_monitor_timer.start()
        self._battery_timer.start()
        if self.log_fh:
            self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
            self._log_timer.start()

        while self._state != PowerCenter.TERMINATE:
            result = signal.pause()
            if self._debug:
                self._log_message('Caught Interrupt')

    def close(self):
        """
        Shuts things down and cancels timers. Set status flag to TERMINATE
        """
        # set state
        if self._debug:
            self._log_message('Setting state to SHUTDOWN')
        self._status = PowerCenter.SHUTDOWN

        # shutdown timers
        if self._power_monitor_timer:
            if self._debug:
                self._log_message('Canceling power monitor timer')
            self._power_monitor_timer.cancel()
        if self._log_timer:
            if self._debug:
                self._log_message('Canceling log timer')
            self._log_timer.cancel()
        if self._battery_timer:
            if self._debug:
                self._log_message('Canceling battery timer')
            self._battery_timer.cancel()

        # shutdown power monitors
        if self._debug:
            self._log_message('Stopping battery power meter')
        self.battery_power.stop()
        if self._debug:
            self._log_message('Stopping dyno power meter')
        self.dyno_power.stop()
        self._trigger.set()
        self.battery_power.close()
        if self._debug:
            self._log_message('Battery power meter closed')
        self.dyno_power.close()
        if self._debug:
            self._log_message('Dyno power meter closed')

        # shutdown LED(s)
        if self.battery_status_led:
            self.battery_status_led.close()

        # shutdown logging
        if self.log_fh:
            self._log_message('Shutting down Power Center')
            self.log_fh.flush()
            self.log_fh.close()
            self.log_fh = None

        # set state
        if self._debug:
            self._log_message('Setting state to TERMINATE')
        self._state = PowerCenter.TERMINATE

    def set_charge_rate(self, rate):
        """
        Sets the charge rate on the AndiceLabs PowerPi
        :param rate: one of {0,1,2,3}
                     0 := charging disabled
                     1 := 1/3 amp
                     2 := 2/3 amp
                     3 := 1 amp
        """
        if rate in [0, 1, 2, 3]:
            if self._debug:
                value = self._i2c_bus.read_byte_data(PowerCenter.AVR_I2C_ADDRESS, PowerCenter.AVR_BATT_CHRG_REG)
                self._log_message('Charge rate was %03f amps' % (value/3))
            self._i2c_bus.write_byte_data(PowerCenter.AVR_I2C_ADDRESS, PowerCenter.AVR_BATT_CHRG_REG, rate)
            if self._debug:
                self._log_message('Charge rate set to %03f amps' % (rate/3))
        else:
            raise ValueError

    def _power_monitor_sync(self):
        """
        Sets event controlling synchronization of power monitors
        """
        self._trigger.set()
        if self._state == PowerCenter.RUNNING:
            self._power_monitor_timer = Timer(PowerCenter.POWER_MONITOR_INTERVAL, self._power_monitor_sync)
            self._power_monitor_timer.start()

    def _check_battery(self):
        """
        Runs battery check and then relaunches timer
        """
        self._update_battery_status()
        if self._state == PowerCenter.RUNNING:
            self._battery_timer = Timer(PowerCenter.CHECK_BATTERY_INTERVAL, self._check_battery)
            self._battery_timer.start()

    def _update_battery_status(self):
        """
        Checks battery voltage and amperage updating LED indication if there is a change
        CHARGING := negative battery amperage
        FULL_CHARGE := positive battery amperage with greater external amperage
        ON_BATTERY := positive battery amperage
        LOW_BATTERY := battery voltage <= LOW_BATTERY_VOLTS
        """
        amperage = self.battery_power.amp
        voltage = self.battery_power.volt
        ext_amperage = self.dyno_power.amp

        if voltage <= PowerCenter.LOW_BATTERY_VOLTS:
            if self.battery_status != PowerCenter.LOW_BATTERY:
                self.battery_status = PowerCenter.LOW_BATTERY
                self.battery_status_led.red()
        elif amperage < 0:
            if self.battery_status != PowerCenter.CHARGING:
                self.battery_status = PowerCenter.CHARGING
                self.battery_status_led.green(True)
        elif ext_amperage > amperage:
            if self.battery_status != PowerCenter.FULL_CHARGE:
                self.battery_status = PowerCenter.FULL_CHARGE
                self.battery_status_led.green()
        else:
            if self.battery_status != PowerCenter.ON_BATTERY:
                self.battery_status = PowerCenter.ON_BATTERY
                self.battery_status_led.blue()

    def _output_log(self):
        """
        Updates logs and relaunches timer
        """
        self._log_power_data()
        if self._state == PowerCenter.RUNNING:
            self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
            self._log_timer.start()

    def _log_power_data(self):
        """
        writes the battery and dyno power values to the log file
        """
        if self.log_fh:
            battery_data = self.battery_power.get()
            battery_watt_seconds = self.battery_power.watt_seconds
            dyno_data = self.dyno_power.get()
            dyno_watt_seconds = self.dyno_power.watt_seconds
            message = ',%s,%f,%s,%f' % (battery_data.csv(), battery_watt_seconds, dyno_data.csv(), dyno_watt_seconds)
            self._log_message(message)

    def _log_message(self, message):
        """
        writes message to log file inserting a timestamp
        :param message: string
        """
        if self.log_fh:
            print('%s %s' % (datetime.now(), message), file=self.log_fh)
        if self._debug:
            print('%s %s' % (datetime.now(), message), file=sys.stderr)

    def _sig_handler(self, signum, frame):
        """
        Handles system signals. SIGINT, SIGTERM to gracefully terminate operation. SIGUSR1 will toggle
        data logging.
        :param signum:
        :param frame:
        """
        if signum in [signal.SIGTERM, signal.SIGINT]:
            if self._debug:
                self._log_message('Received signal %d' % signum)
            self.close()

        elif signum == signal.SIGUSR1:
            if self.log_fh:
                self._log_message('Logging disabled')
                self.log_fh.flush()
                self.log_fh.close()
                self.log_fh = None
            else:
                try:
                    self.log_fh = open(self.log_file, 'a')
                except:
                    print('Failed to open %s for logging: %s' % (self.log_file, sys.exc_info()[0]), sys.stderr)
                    self.log_fh = None
                    return
                self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
                self._log_timer.start()
                self._log_message('Logging enabled')

def main():
    """
    Instantiates PowerCenter and waits for termination
    """
    pc = PowerCenter()
    pc.run()

if __name__ == "__main__":
    main()<commit_msg>determine battery state only using battery amp and voltage monitoring in case we have no external monitor available<commit_after>
"""
Rickie Kerndt <rkerndt@cs.uoregon.edu
bike_power_center.py
Provides services for monitoring and managing bicycle electrical systems
"""

from __future__ import print_function
import sys
sys.path.append('/home/pi/lib/python')

import signal
import ina219
import power_meter as pm
import rgb
from threading import Event, Timer
from datetime import datetime
import smbus

class PowerCenter():
    """
    Methods for monitoring power generating, consumption, and modifying on bicycle electronics to control
    power consumption.
    """

    CHARGING    = 0
    FULL_CHARGE = 1
    ON_BATTERY  = 2
    LOW_BATTERY = 3
    LOW_BATTERY_VOLTS = 3.2
    FULL_CHARGE_AMPS_POS = 0.003    # maximum batt amp draw on full charge with external power
    FULL_CHARGE_AMPS_NEG = -0.1     # maximum batt charge amp considered at full charge

    LOG_FILE = "/var/log/power_center.log"
    RUNNING = 0
    SHUTDOWN = 1
    TERMINATE = 2

    # timer intervals
    CHECK_BATTERY_INTERVAL = 1.0
    LOG_DATA_INTERVAL = 1.0
    POWER_MONITOR_INTERVAL = 0.08

    DEBUG = False

    # avr constants
    AVR_I2C_BUS = 1
    AVR_I2C_ADDRESS = 0x21
    AVR_BATT_CHRG_REG = 23  # sets the battery charging rate (1/3, 2/3, 1 amp)

    def __init__(self):
        """
        Instantiates power center which for now just monitors battery and external power ina219 devices.
        """
        self._trigger = Event()
        self._state = None
        self.battery_power = pm.PowerMeter(pm.INA219_Monitor(0.1, 0x40, 1, ina219.INA219_CALIB_32V_1A, 128),
                                           self._trigger)
        self.dyno_power = pm.PowerMeter(pm.INA219_Monitor(0.1, 0x41, 1, ina219.INA219_CALIB_32V_2A, 128),
                                        self._trigger)
        self.log_file = PowerCenter.LOG_FILE
        self.log_fh = None
        self.battery_status = None
        self.battery_status_led = rgb.RGB_led(21, 20, 16)
        self._battery_timer = Timer(PowerCenter.CHECK_BATTERY_INTERVAL, self._check_battery)
        self._log_timer = None
        self._power_monitor_timer = Timer(PowerCenter.POWER_MONITOR_INTERVAL, self._power_monitor_sync)
        self._debug = PowerCenter.DEBUG
        self._i2c_bus = smbus.SMBus(PowerCenter.AVR_I2C_BUS)

        signal.signal(signal.SIGTERM, self._sig_handler)
        signal.signal(signal.SIGINT, self._sig_handler)
        signal.signal(signal.SIGUSR1, self._sig_handler)

    def run(self):
        """
        Starts things up and launches timers
        """
        self._state = PowerCenter.RUNNING
        self.battery_power.open()
        self.dyno_power.open()
        self._power_monitor_timer.start()
        self._battery_timer.start()
        if self.log_fh:
            self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
            self._log_timer.start()

        while self._state != PowerCenter.TERMINATE:
            result = signal.pause()
            if self._debug:
                self._log_message('Caught Interrupt')

    def close(self):
        """
        Shuts things down and cancels timers. Set status flag to TERMINATE
        """
        # set state
        if self._debug:
            self._log_message('Setting state to SHUTDOWN')
        self._status = PowerCenter.SHUTDOWN

        # shutdown timers
        if self._power_monitor_timer:
            if self._debug:
                self._log_message('Canceling power monitor timer')
            self._power_monitor_timer.cancel()
        if self._log_timer:
            if self._debug:
                self._log_message('Canceling log timer')
            self._log_timer.cancel()
        if self._battery_timer:
            if self._debug:
                self._log_message('Canceling battery timer')
            self._battery_timer.cancel()

        # shutdown power monitors
        if self._debug:
            self._log_message('Stopping battery power meter')
        self.battery_power.stop()
        if self._debug:
            self._log_message('Stopping dyno power meter')
        self.dyno_power.stop()
        self._trigger.set()
        self.battery_power.close()
        if self._debug:
            self._log_message('Battery power meter closed')
        self.dyno_power.close()
        if self._debug:
            self._log_message('Dyno power meter closed')

        # shutdown LED(s)
        if self.battery_status_led:
            self.battery_status_led.close()

        # shutdown logging
        if self.log_fh:
            self._log_message('Shutting down Power Center')
            self.log_fh.flush()
            self.log_fh.close()
            self.log_fh = None

        # set state
        if self._debug:
            self._log_message('Setting state to TERMINATE')
        self._state = PowerCenter.TERMINATE

    def set_charge_rate(self, rate):
        """
        Sets the charge rate on the AndiceLabs PowerPi
        :param rate: one of {0,1,2,3}
                     0 := charging disabled
                     1 := 1/3 amp
                     2 := 2/3 amp
                     3 := 1 amp
        """
        if rate in [0, 1, 2, 3]:
            if self._debug:
                value = self._i2c_bus.read_byte_data(PowerCenter.AVR_I2C_ADDRESS, PowerCenter.AVR_BATT_CHRG_REG)
                self._log_message('Charge rate was %03f amps' % (value/3))
            self._i2c_bus.write_byte_data(PowerCenter.AVR_I2C_ADDRESS, PowerCenter.AVR_BATT_CHRG_REG, rate)
            if self._debug:
                self._log_message('Charge rate set to %03f amps' % (rate/3))
        else:
            raise ValueError

    def _power_monitor_sync(self):
        """
        Sets event controlling synchronization of power monitors
        """
        self._trigger.set()
        if self._state == PowerCenter.RUNNING:
            self._power_monitor_timer = Timer(PowerCenter.POWER_MONITOR_INTERVAL, self._power_monitor_sync)
            self._power_monitor_timer.start()

    def _check_battery(self):
        """
        Runs battery check and then relaunches timer
        """
        self._update_battery_status()
        if self._state == PowerCenter.RUNNING:
            self._battery_timer = Timer(PowerCenter.CHECK_BATTERY_INTERVAL, self._check_battery)
            self._battery_timer.start()

    def _update_battery_status(self):
        """
        Checks battery voltage and amperage updating LED indication if there is a change
        CHARGING := negative battery amperage
        FULL_CHARGE := positive battery amperage below FULL_CHARGE_AMPS
        ON_BATTERY := positive battery amperage
        LOW_BATTERY := battery voltage <= LOW_BATTERY_VOLTS
        """
        amperage = self.battery_power.amp
        voltage = self.battery_power.volt

        if voltage <= PowerCenter.LOW_BATTERY_VOLTS:
            if self.battery_status != PowerCenter.LOW_BATTERY:
                self.battery_status = PowerCenter.LOW_BATTERY
                self.battery_status_led.red()
        elif amperage < PowerCenter.FULL_CHARGE_AMPS_NEG:
            if self.battery_status != PowerCenter.CHARGING:
                self.battery_status = PowerCenter.CHARGING
                self.battery_status_led.green(True)
        elif amperage < PowerCenter.FULL_CHARGE_AMPS_POS:
            if self.battery_status != PowerCenter.FULL_CHARGE:
                self.battery_status = PowerCenter.FULL_CHARGE
                self.battery_status_led.green()
        else:
            if self.battery_status != PowerCenter.ON_BATTERY:
                self.battery_status = PowerCenter.ON_BATTERY
                self.battery_status_led.blue()

    def _output_log(self):
        """
        Updates logs and relaunches timer
        """
        self._log_power_data()
        if self._state == PowerCenter.RUNNING:
            self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
            self._log_timer.start()

    def _log_power_data(self):
        """
        writes the battery and dyno power values to the log file
        """
        if self.log_fh:
            battery_data = self.battery_power.get()
            battery_watt_seconds = self.battery_power.watt_seconds
            dyno_data = self.dyno_power.get()
            dyno_watt_seconds = self.dyno_power.watt_seconds
            message = ',%s,%f,%s,%f' % (battery_data.csv(), battery_watt_seconds, dyno_data.csv(), dyno_watt_seconds)
            self._log_message(message)

    def _log_message(self, message):
        """
        writes message to log file inserting a timestamp
        :param message: string
        """
        if self.log_fh:
            print('%s %s' % (datetime.now(), message), file=self.log_fh)
        if self._debug:
            print('%s %s' % (datetime.now(), message), file=sys.stderr)

    def _sig_handler(self, signum, frame):
        """
        Handles system signals. SIGINT, SIGTERM to gracefully terminate operation. SIGUSR1 will toggle
        data logging.
        :param signum:
        :param frame:
        """
        if signum in [signal.SIGTERM, signal.SIGINT]:
            if self._debug:
                self._log_message('Received signal %d' % signum)
            self.close()

        elif signum == signal.SIGUSR1:
            if self.log_fh:
                self._log_message('Logging disabled')
                self.log_fh.flush()
                self.log_fh.close()
                self.log_fh = None
            else:
                try:
                    self.log_fh = open(self.log_file, 'a')
                except:
                    print('Failed to open %s for logging: %s' % (self.log_file, sys.exc_info()[0]), sys.stderr)
                    self.log_fh = None
                    return
                self._log_timer = Timer(PowerCenter.LOG_DATA_INTERVAL, self._output_log)
                self._log_timer.start()
                self._log_message('Logging enabled')

def main():
    """
    Instantiates PowerCenter and waits for termination
    """
    pc = PowerCenter()
    pc.run()

if __name__ == "__main__":
    main()<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
vm.py -- create and run a virtual machine based on the standard
         salvus_base template with the given memory and vcpus, and add
         the vm to our tinc VPN.  When this script terminates, the vm
         is destroyed, undefined, and the image file associated with
         it is deleted.
"""

#######################################################################
# Copyright (c) William Stein, 2012.  Not open source or free. Will be
# assigned to University of Washington.
#######################################################################

import logging, os, shutil, socket, tempfile, time

from admin import run, sh

conf_path = os.path.join(os.path.split(os.path.realpath(__file__))[0], 'conf')

###########################################
# kvm -- via libvirt
###########################################

def virsh(command, name):
    #return run(['virsh', '--connect', 'qemu:///session', command, name], verbose=False).strip()
    return run(['virsh', '--connect', 'qemu:///system', command, name], verbose=False).strip()

def run_kvm(ip_address, hostname, vcpus, ram, vnc, disk, base, fstab):
    #################################
    # create the copy-on-write image
    #################################
    t = time.time()
    img_path = os.path.join(os.environ['HOME'], 'vm', 'images')
    base_img_path = os.path.join(img_path, 'base')
    if not os.path.exists(base_img_path):
        os.makedirs(base_img_path)
    persistent_img_path = os.path.join(img_path, 'persistent')
    if not os.path.exists(persistent_img_path):
        os.makedirs(persistent_img_path)
    temporary_img_path = os.path.join(img_path, 'temporary')
    if not os.path.exists(temporary_img_path):
        os.makedirs(temporary_img_path)
    new_img = os.path.join(temporary_img_path, hostname + '.img')

    if os.path.exists(new_img):
        raise RuntimeError("the image '%s' already exists; maybe the virtual machine is already running?"%new_img)

    if not base.endswith('.img'): base += '.img'
    base_img = os.path.join(base_img_path, base)
    try:
        #################################
        # create disk images
        #################################
        # Transient image based on our template
        sh['qemu-img', 'create', '-b', base_img, '-f', 'qcow2', new_img]
        log.info("created %s in %s seconds", new_img, time.time()-t); t = time.time()
        # Persistent image(s)
        persistent_images = []
        for name, size, fstype, format in disk:
            persistent_images.append((os.path.join(persistent_img_path, '%s-%s.img'%(hostname, name)), name, fstype, format))
            img = persistent_images[-1][0]
            if not os.path.exists(img):
                os.chdir(persistent_img_path)
                temp = None
                try:
                    # Unfortunately, guestfish doesn't support xfs.
                    sh['qemu-img', 'create', '-f', format, img, '%sG'%size]
                    # See salvus/salvus/scripts/salvus_nbd_format.py
                    if fstype != 'none':
                        log.info("WARNING: formatting filesystem can take a long time...")
                        run(['sudo', '/usr/local/bin/salvus_nbd_format.py', fstype, img], maxtime=1800)
                    sh['chgrp', 'kvm', img]
                    sh['chmod', 'g+rw', img]
                finally:
                    if temp is not None:
                        shutil.rmtree(temp)
                        if os.path.exists('test1.img'):
                            os.unlink('test1.img')
            else:
                pass
                # TODO: else -- if too small, enlarge image if possible

        #################################
        # configure the vm's image
        #################################
        # - mount the image in a temp directory
        tincname = hostname.replace('-','_')
        vmhost_tincname = socket.gethostname().replace('-','_')
        try:
            tmp_path = tempfile.mkdtemp()
            try:
                run(['guestmount', '-i', '-a', new_img, '--rw', tmp_path], maxtime=60)

                #### hostname ####
                hostname_file = os.path.join(tmp_path,'etc/hostname')
                if not os.path.exists(hostname_file):
                    raise RuntimeError("missing /etc/hostname in the VM image; probably the guestmount command is not working, and the fix is probably to type 'sudo chmod a+r /boot/vmlinuz-*'")

                os.unlink(hostname_file)
                open(hostname_file,'w').write(hostname)
                hosts_file = os.path.join(tmp_path, 'etc/hosts')
                hosts = open(hosts_file).read()
                os.unlink(hosts_file)
                open(hosts_file,'w').write("%s\n127.0.1.1  %s\n"%(hosts, hostname))

                #### tinc vpn ####
                tinc_path = os.path.join(tmp_path, 'home/salvus/salvus/salvus/data/local/etc/tinc/')
                open(os.path.join(tinc_path, 'tinc-up'),'w').write(
                    "#!/bin/sh\nifconfig $INTERFACE %s netmask 255.192.0.0"%ip_address)
                open(os.path.join(tinc_path, 'tinc.conf'),'w').write(
                    "Name = %s\nConnectTo = %s"%(tincname, vmhost_tincname))
                rsa_key_priv = os.path.join(tinc_path, 'rsa_key.priv')
                rsa_key_pub = os.path.join(tinc_path, 'hosts', tincname)
                if os.path.exists(rsa_key_priv): os.unlink(rsa_key_priv)
                if os.path.exists(rsa_key_pub): os.unlink(rsa_key_pub)
                sh['tincd', '--config', tinc_path, '-K']
                host_file = os.path.join(tinc_path, 'hosts', tincname)
                public_key = open(rsa_key_pub).read().strip()
                open(host_file,'w').write("Cipher = aes-128-cbc\nSubnet = %s/32\n%s"%(ip_address, public_key))
                # put the tinc public key in our local db, so that the vm can connect to host.
                shutil.copyfile(host_file, os.path.join(conf_path, 'tinc_hosts', tincname))

                #### persisent disks ####
                fstab_file = os.path.join(tmp_path, 'etc/fstab')
                try:
                    f = open(fstab_file,'a')
                    for i,x in enumerate(persistent_images):
                        if x[2] != 'none':   # using defaults instead of nobootwait, since nobootwait causes trouble with firstboot.py
                            f.write("\n/dev/vd%s1   /mnt/%s   %s   defaults  0   2\n"%(chr(98+i),x[1],x[2]))
                            mnt_point = os.path.join(tmp_path, 'mnt/%s'%x[1])
                            os.makedirs(mnt_point)
                    f.write('\n'+fstab+'\n')
                    for x in fstab.splitlines():
                        v = x.split()
                        if not x.lstrip().startswith('#') and len(v) >= 2:
                            mnt_point = os.path.join(tmp_path, v[1].lstrip('/'))
                            os.makedirs(mnt_point)

                finally:
                    f.close()

            finally:
                # - unmount image and remove tmp_path
                sh['fusermount', '-u', tmp_path]
        finally:
            shutil.rmtree(tmp_path)

        log.info("configured image in %s seconds", time.time()-t); t = time.time()

        #################################
        # create and start the vm itself
        #################################
        try:
            cmd = ['virt-install',
                   '--connect', 'qemu:///system',
                   '--cpu', 'host',
                   '--network', 'network:default,model=virtio',
                   '--name', hostname,
                   '--vcpus', vcpus,
                   '--ram', 1024*ram,
                   '--import',
                   '--disk', (new_img + ',device=disk,bus=virtio,format=qcow2,cache=writeback'),
                   '--noautoconsole']

            if vnc:
                cmd.extend(['--graphics', 'vnc,port=%s'%vnc])

            for x in persistent_images:
                cmd.extend(['--disk', '%s,bus=virtio,cache=writeback,format=%s'%(x[0],x[3])])

            os.system("ls -lh %s"%new_img)
            sh['chgrp', 'kvm', new_img]
            sh['chmod', 'g+rw', new_img]
            os.system("ls -lh %s"%new_img)

            log.info(run(cmd, maxtime=120))

            log.info("created new virtual machine in %s seconds -- now running", time.time()-t); t = time.time()

            ##########################################################################
            # - run until vm terminates or we receive term signal, undefined, destroy
            ##########################################################################
            while virsh('domstate', hostname) == 'running':
                 # TODO: this is polling, which violates an axiom.  We absolutely
                 # must rewrite this to be event driven!!!?
                time.sleep(1)
        except Exception, e:
            log.info("error creating virtual machine -- %s"%e)
        finally:
            # clean up
            virsh('undefine', hostname)
            virsh('destroy', hostname)
            pass

    finally:
        try:
            os.unlink(os.path.join(conf_path, 'tinc_hosts', tincname))
        except: pass
        try:
            os.unlink(new_img)
        except: pass

def run_virtualbox(ip_address, hostname, vcpus, ram, vnc, disk, base):
    raise NotImplementedError

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="vm.py starts virtual machine with given IP address and type on this computer")

    parser.add_argument("-d", dest="daemon", default=False, action="store_const", const=True,
                        help="daemon mode (default: False)")
    parser.add_argument("--ip_address", dest="ip_address", type=str, required=True,
                        help="ip address of the virtual machine on the VPN")
    parser.add_argument("--hostname", dest="hostname", type=str, default='',
                        help="hostname of the virtual machine on the VPN")
    parser.add_argument("--vcpus", dest="vcpus", type=str, default="2",
                        help="number of virtual cpus")
    parser.add_argument("--ram", dest="ram", type=int, default=4,
                        help="Gigabytes of ram")
    parser.add_argument("--vnc", dest="vnc", type=int, default=0,
                        help="VNC console port (default: 0 -- no VNC)")
    parser.add_argument("--pidfile", dest="pidfile", type=str, default='',
                        help="store pid in this file")
    parser.add_argument("-l", dest='log_level', type=str, default='INFO',
                        help="log level (default: INFO) useful options include WARNING and DEBUG")
    parser.add_argument("--logfile", dest="logfile", type=str, default='',
                        help="store log in this file (default: '' = don't log to a file)")
    parser.add_argument("--vm_type", dest="vm_type", type=str, default="kvm",
                        help="type of virtual machine to create ('kvm', 'virtualbox')")
    parser.add_argument("--disk", dest="disk", type=str, default="",
                        help="persistent disks: '--disk=cassandra:64:ext4:qcow2,backup:10:xfs:qcow2' makes two sparse qcow2 images of size 64GB and 10GB if they don't exist, one formated ext4 the other xfs, and mounted as /mnt/cassandra and /mnt/backup; if they exist and are smaller than the given size, they are automatically expanded.  The disks are stored as ~/vm/images/ip_address-cassandra.img, etc.  More precisely, the format is --disk=[name]:[size]:[raw|qcow2]:[ext4|xfs|none].  If format is none, then the disk is not mounted in fstab.")
    parser.add_argument("--fstab", dest="fstab", type=str, default="", help="custom string to add to the end of /etc/fstab; each mountpoint in that string will be created if necessary")
    parser.add_argument('--base', dest='base', type=str, default='salvus',
                        help="template image in ~/vm/images/base on which to base this machine; must *not* be running (default: salvus).")

    args = parser.parse_args()

    if args.logfile:
        args.logfile = os.path.abspath(args.logfile)
    if args.pidfile:
        args.pidfile = os.path.abspath(args.pidfile)
    if args.ip_address.count('.') == 0:
        args.ip_address = '10.1.1.' + args.ip_address
    elif args.ip_address.count('.') == 1:
        args.ip_address = '10.1.' + args.ip_address
    elif args.ip_address.count('.') == 2:
        args.ip_address = '10.' + args.ip_address

    assert args.ip_address.startswith('10.'), "ip address must belong to the class A network 10."

    args.hostname = args.hostname if args.hostname else args.ip_address.replace('.','dot')

    try:
        disk = []
        if args.disk:
            for x in args.disk.split(','):
                a = x.split(':')
                if len(a) == 1:
                    a.append('1')
                if len(a) == 2:
                    a.append('ext4')  # default filesystem type
                if len(a) == 3:
                    a.append('raw')
                assert len(a) == 4
                disk.append(a)
    except (IndexError, ValueError):
        raise RuntimeError("--disk option must be of the form 'name1:size1[:fstype][:format],name2:size2[:fstype][:format],...', with size in gigabytes")

    def main():
        global log

        logging.basicConfig()
        log = logging.getLogger('vm')
        log.setLevel(logging.INFO)

        if args.log_level:
            level = getattr(logging, args.log_level.upper())
            log.setLevel(level)

        if args.logfile:
            log.addHandler(logging.FileHandler(args.logfile))

        import admin   # take over the admin logger
        admin.log = log

        log.info("logger started")

        if args.pidfile:
            open(args.pidfile,'w').write(str(os.getpid()))

        if args.vm_type == 'kvm':
            run_kvm(args.ip_address, args.hostname, args.vcpus, args.ram, args.vnc, disk, args.base, fstab=args.fstab)
        elif args.vm_type == 'virtualbox':
            raise NotImplementedError
            run_virtualbox(args.ip_address, args.hostname, args.vcpus, args.ram, args.vnc, disk, args.base)
        else:
            print "Unknown vm_type '%s'"%args.vm_type
            sys.exit(1)

    try:
        if args.daemon:
            import daemon
            daemon.daemonize(args.pidfile)
            main()
        else:
            main()
    finally:
        if args.pidfile and os.path.exists(args.pidfile):
            os.unlink(args.pidfile)
<commit_msg>tinc: increate keyexpire, enable compression, force tcponly<commit_after>#!/usr/bin/env python
"""
vm.py -- create and run a virtual machine based on the standard
         salvus_base template with the given memory and vcpus, and add
         the vm to our tinc VPN.  When this script terminates, the vm
         is destroyed, undefined, and the image file associated with
         it is deleted.
"""

#######################################################################
# Copyright (c) William Stein, 2012.  Not open source or free. Will be
# assigned to University of Washington.
#######################################################################

import logging, os, shutil, socket, tempfile, time

from admin import run, sh

conf_path = os.path.join(os.path.split(os.path.realpath(__file__))[0], 'conf')

###########################################
# kvm -- via libvirt
###########################################

def virsh(command, name):
    #return run(['virsh', '--connect', 'qemu:///session', command, name], verbose=False).strip()
    return run(['virsh', '--connect', 'qemu:///system', command, name], verbose=False).strip()

def run_kvm(ip_address, hostname, vcpus, ram, vnc, disk, base, fstab):
    #################################
    # create the copy-on-write image
    #################################
    t = time.time()
    img_path = os.path.join(os.environ['HOME'], 'vm', 'images')
    base_img_path = os.path.join(img_path, 'base')
    if not os.path.exists(base_img_path):
        os.makedirs(base_img_path)
    persistent_img_path = os.path.join(img_path, 'persistent')
    if not os.path.exists(persistent_img_path):
        os.makedirs(persistent_img_path)
    temporary_img_path = os.path.join(img_path, 'temporary')
    if not os.path.exists(temporary_img_path):
        os.makedirs(temporary_img_path)
    new_img = os.path.join(temporary_img_path, hostname + '.img')

    if os.path.exists(new_img):
        raise RuntimeError("the image '%s' already exists; maybe the virtual machine is already running?"%new_img)

    if not base.endswith('.img'): base += '.img'
    base_img = os.path.join(base_img_path, base)
    try:
        #################################
        # create disk images
        #################################
        # Transient image based on our template
        sh['qemu-img', 'create', '-b', base_img, '-f', 'qcow2', new_img]
        log.info("created %s in %s seconds", new_img, time.time()-t); t = time.time()
        # Persistent image(s)
        persistent_images = []
        for name, size, fstype, format in disk:
            persistent_images.append((os.path.join(persistent_img_path, '%s-%s.img'%(hostname, name)), name, fstype, format))
            img = persistent_images[-1][0]
            if not os.path.exists(img):
                os.chdir(persistent_img_path)
                temp = None
                try:
                    # Unfortunately, guestfish doesn't support xfs.
                    sh['qemu-img', 'create', '-f', format, img, '%sG'%size]
                    # See salvus/salvus/scripts/salvus_nbd_format.py
                    if fstype != 'none':
                        log.info("WARNING: formatting filesystem can take a long time...")
                        run(['sudo', '/usr/local/bin/salvus_nbd_format.py', fstype, img], maxtime=1800)
                    sh['chgrp', 'kvm', img]
                    sh['chmod', 'g+rw', img]
                finally:
                    if temp is not None:
                        shutil.rmtree(temp)
                        if os.path.exists('test1.img'):
                            os.unlink('test1.img')
            else:
                pass
                # TODO: else -- if too small, enlarge image if possible

        #################################
        # configure the vm's image
        #################################
        # - mount the image in a temp directory
        tincname = hostname.replace('-','_')
        vmhost_tincname = socket.gethostname().replace('-','_')
        try:
            tmp_path = tempfile.mkdtemp()
            try:
                run(['guestmount', '-i', '-a', new_img, '--rw', tmp_path], maxtime=60)

                #### hostname ####
                hostname_file = os.path.join(tmp_path,'etc/hostname')
                if not os.path.exists(hostname_file):
                    raise RuntimeError("missing /etc/hostname in the VM image; probably the guestmount command is not working, and the fix is probably to type 'sudo chmod a+r /boot/vmlinuz-*'")

                os.unlink(hostname_file)
                open(hostname_file,'w').write(hostname)
                hosts_file = os.path.join(tmp_path, 'etc/hosts')
                hosts = open(hosts_file).read()
                os.unlink(hosts_file)
                open(hosts_file,'w').write("%s\n127.0.1.1  %s\n"%(hosts, hostname))

                #### tinc vpn ####
                tinc_path = os.path.join(tmp_path, 'home/salvus/salvus/salvus/data/local/etc/tinc/')
                open(os.path.join(tinc_path, 'tinc-up'),'w').write(
                    "#!/bin/sh\nifconfig $INTERFACE %s netmask 255.192.0.0"%ip_address)
                open(os.path.join(tinc_path, 'tinc.conf'),'w').write(
                    "Name = %s\nKeyExpire =86400\nConnectTo = %s"%(tincname, vmhost_tincname))
                rsa_key_priv = os.path.join(tinc_path, 'rsa_key.priv')
                rsa_key_pub = os.path.join(tinc_path, 'hosts', tincname)
                if os.path.exists(rsa_key_priv): os.unlink(rsa_key_priv)
                if os.path.exists(rsa_key_pub): os.unlink(rsa_key_pub)
                sh['tincd', '--config', tinc_path, '-K']
                host_file = os.path.join(tinc_path, 'hosts', tincname)
                public_key = open(rsa_key_pub).read().strip()
                open(host_file,'w').write("TCPonly=yes\nCompression=10\nCipher = aes-128-cbc\nSubnet = %s/32\n%s"%(ip_address, public_key))
                # put the tinc public key in our local db, so that the vm can connect to host.
                shutil.copyfile(host_file, os.path.join(conf_path, 'tinc_hosts', tincname))

                #### persisent disks ####
                fstab_file = os.path.join(tmp_path, 'etc/fstab')
                try:
                    f = open(fstab_file,'a')
                    for i,x in enumerate(persistent_images):
                        if x[2] != 'none':   # using defaults instead of nobootwait, since nobootwait causes trouble with firstboot.py
                            f.write("\n/dev/vd%s1   /mnt/%s   %s   defaults  0   2\n"%(chr(98+i),x[1],x[2]))
                            mnt_point = os.path.join(tmp_path, 'mnt/%s'%x[1])
                            os.makedirs(mnt_point)
                    f.write('\n'+fstab+'\n')
                    for x in fstab.splitlines():
                        v = x.split()
                        if not x.lstrip().startswith('#') and len(v) >= 2:
                            mnt_point = os.path.join(tmp_path, v[1].lstrip('/'))
                            os.makedirs(mnt_point)

                finally:
                    f.close()

            finally:
                # - unmount image and remove tmp_path
                sh['fusermount', '-u', tmp_path]
        finally:
            shutil.rmtree(tmp_path)

        log.info("configured image in %s seconds", time.time()-t); t = time.time()

        #################################
        # create and start the vm itself
        #################################
        try:
            cmd = ['virt-install',
                   '--connect', 'qemu:///system',
                   '--cpu', 'host',
                   '--network', 'network:default,model=virtio',
                   '--name', hostname,
                   '--vcpus', vcpus,
                   '--ram', 1024*ram,
                   '--import',
                   '--disk', (new_img + ',device=disk,bus=virtio,format=qcow2,cache=writeback'),
                   '--noautoconsole']

            if vnc:
                cmd.extend(['--graphics', 'vnc,port=%s'%vnc])

            for x in persistent_images:
                cmd.extend(['--disk', '%s,bus=virtio,cache=writeback,format=%s'%(x[0],x[3])])

            os.system("ls -lh %s"%new_img)
            sh['chgrp', 'kvm', new_img]
            sh['chmod', 'g+rw', new_img]
            os.system("ls -lh %s"%new_img)

            log.info(run(cmd, maxtime=120))

            log.info("created new virtual machine in %s seconds -- now running", time.time()-t); t = time.time()

            ##########################################################################
            # - run until vm terminates or we receive term signal, undefined, destroy
            ##########################################################################
            while virsh('domstate', hostname) == 'running':
                 # TODO: this is polling, which violates an axiom.  We absolutely
                 # must rewrite this to be event driven!!!?
                time.sleep(1)
        except Exception, e:
            log.info("error creating virtual machine -- %s"%e)
        finally:
            # clean up
            virsh('undefine', hostname)
            virsh('destroy', hostname)
            pass

    finally:
        try:
            os.unlink(os.path.join(conf_path, 'tinc_hosts', tincname))
        except: pass
        try:
            os.unlink(new_img)
        except: pass

def run_virtualbox(ip_address, hostname, vcpus, ram, vnc, disk, base):
    raise NotImplementedError

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="vm.py starts virtual machine with given IP address and type on this computer")

    parser.add_argument("-d", dest="daemon", default=False, action="store_const", const=True,
                        help="daemon mode (default: False)")
    parser.add_argument("--ip_address", dest="ip_address", type=str, required=True,
                        help="ip address of the virtual machine on the VPN")
    parser.add_argument("--hostname", dest="hostname", type=str, default='',
                        help="hostname of the virtual machine on the VPN")
    parser.add_argument("--vcpus", dest="vcpus", type=str, default="2",
                        help="number of virtual cpus")
    parser.add_argument("--ram", dest="ram", type=int, default=4,
                        help="Gigabytes of ram")
    parser.add_argument("--vnc", dest="vnc", type=int, default=0,
                        help="VNC console port (default: 0 -- no VNC)")
    parser.add_argument("--pidfile", dest="pidfile", type=str, default='',
                        help="store pid in this file")
    parser.add_argument("-l", dest='log_level', type=str, default='INFO',
                        help="log level (default: INFO) useful options include WARNING and DEBUG")
    parser.add_argument("--logfile", dest="logfile", type=str, default='',
                        help="store log in this file (default: '' = don't log to a file)")
    parser.add_argument("--vm_type", dest="vm_type", type=str, default="kvm",
                        help="type of virtual machine to create ('kvm', 'virtualbox')")
    parser.add_argument("--disk", dest="disk", type=str, default="",
                        help="persistent disks: '--disk=cassandra:64:ext4:qcow2,backup:10:xfs:qcow2' makes two sparse qcow2 images of size 64GB and 10GB if they don't exist, one formated ext4 the other xfs, and mounted as /mnt/cassandra and /mnt/backup; if they exist and are smaller than the given size, they are automatically expanded.  The disks are stored as ~/vm/images/ip_address-cassandra.img, etc.  More precisely, the format is --disk=[name]:[size]:[raw|qcow2]:[ext4|xfs|none].  If format is none, then the disk is not mounted in fstab.")
    parser.add_argument("--fstab", dest="fstab", type=str, default="", help="custom string to add to the end of /etc/fstab; each mountpoint in that string will be created if necessary")
    parser.add_argument('--base', dest='base', type=str, default='salvus',
                        help="template image in ~/vm/images/base on which to base this machine; must *not* be running (default: salvus).")

    args = parser.parse_args()

    if args.logfile:
        args.logfile = os.path.abspath(args.logfile)
    if args.pidfile:
        args.pidfile = os.path.abspath(args.pidfile)
    if args.ip_address.count('.') == 0:
        args.ip_address = '10.1.1.' + args.ip_address
    elif args.ip_address.count('.') == 1:
        args.ip_address = '10.1.' + args.ip_address
    elif args.ip_address.count('.') == 2:
        args.ip_address = '10.' + args.ip_address

    assert args.ip_address.startswith('10.'), "ip address must belong to the class A network 10."

    args.hostname = args.hostname if args.hostname else args.ip_address.replace('.','dot')

    try:
        disk = []
        if args.disk:
            for x in args.disk.split(','):
                a = x.split(':')
                if len(a) == 1:
                    a.append('1')
                if len(a) == 2:
                    a.append('ext4')  # default filesystem type
                if len(a) == 3:
                    a.append('raw')
                assert len(a) == 4
                disk.append(a)
    except (IndexError, ValueError):
        raise RuntimeError("--disk option must be of the form 'name1:size1[:fstype][:format],name2:size2[:fstype][:format],...', with size in gigabytes")

    def main():
        global log

        logging.basicConfig()
        log = logging.getLogger('vm')
        log.setLevel(logging.INFO)

        if args.log_level:
            level = getattr(logging, args.log_level.upper())
            log.setLevel(level)

        if args.logfile:
            log.addHandler(logging.FileHandler(args.logfile))

        import admin   # take over the admin logger
        admin.log = log

        log.info("logger started")

        if args.pidfile:
            open(args.pidfile,'w').write(str(os.getpid()))

        if args.vm_type == 'kvm':
            run_kvm(args.ip_address, args.hostname, args.vcpus, args.ram, args.vnc, disk, args.base, fstab=args.fstab)
        elif args.vm_type == 'virtualbox':
            raise NotImplementedError
            run_virtualbox(args.ip_address, args.hostname, args.vcpus, args.ram, args.vnc, disk, args.base)
        else:
            print "Unknown vm_type '%s'"%args.vm_type
            sys.exit(1)

    try:
        if args.daemon:
            import daemon
            daemon.daemonize(args.pidfile)
            main()
        else:
            main()
    finally:
        if args.pidfile and os.path.exists(args.pidfile):
            os.unlink(args.pidfile)
<|endoftext|>


<commit_before># coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

from __future__ import division, unicode_literals

import re
import csv
import collections
import itertools
from io import open
import math
from six.moves import zip
import logging

from monty.json import MSONable, MontyDecoder

import numpy as np

from pymatgen.core.structure import Molecule
from pymatgen.io.qchem.outputs import edges_from_babel, build_MoleculeGraph, is_isomorphic
import networkx as nx

# have_babel = True
# try:
#     from pymatgen.io.babel import BabelMolAdaptor
#     import openbabel as ob
# except ImportError:
#     print("Cannot find OpenBabel! Thus, bonds must be provided by the user.")
#     have_babel = False

"""
This module defines tools to calculate bond dissocation energies.
"""

__author__ = "Samuel Blau"
__copyright__ = "Copyright 2018, The Materials Project"
__version__ = "1.0"
__maintainer__ = "Samuel Blau"
__email__ = "samblau1@gmail.com"
__status__ = "Alpha"
__date__ = "7/26/18"

logger = logging.getLogger(__name__)

class BondDissociationEnergies(MSONable):

    def __init__(self, molecule_entry, fragment_entries):
        """
        Standard constructor for bond dissociation energies.

        Args:

        Get list of all bonds in target molecule
        Build molecule graph of target molecule
        Loop through bonds aka edges and attempt to split into disconnected subgraphs
            On success:
                Search through fragments: find entries with initial OR final molecules which are isomorphic
                Should be three entires per fragment: original charge, OC+1, OC-1
                If there are too few entries:
                    If one of the fragments is an H atom, you should only find two. H+ should be set (to what value???)
                    If fragment matches initial, but not final structure:
                        Just accept the rearrangement as part of the energetic cost of dissociation?
                        At the very least, flag this structure change in the eventual entry
                    If fragment matches final, but not initial structure:
                        Ignore unless no other fragment matches either?
                    If fragment is unstable:
                        Find its subfragments? Is that even sensical?
                        Just pass?
                    If fragment truly cannot be found, aka has not been calculated or calculate failed to complete:
                        Tell user to calculate it and pass
                If there are too many entries:
                    Get rid of duplicates
                        Going to be annoying given time stamps, rounding errors, etc
                    Remove those whose initial rems don't conform to current defaults - Happens before passing
                    If still more than three, for now, isolate differences, report to user, and grab most recent
                    Just take more negative?
                Grab energies of each fragment at all three charges
                If target molecule is neutral:
                    Calculate E_frag1(0)  + E_frag2(0)
                    Calculate E_frag1(+1) + E_frag2(-1)
                    Calculate E_frag1(-1) + E_frag2(+1)
                If target molecule is +1:
                    Calculate E_frag1(0)  + E_frag2(+1)
                    Calculate E_frag1(+1) + E_frag2(0)
                    Calculate E_frag1(+2) + E_frag2(-1)?
                    Calculate E_frag1(-1) + E_frag2(+2)?
                If target molecule is -1:
                    Calculate E_frag1(0)  + E_frag2(-1)
                    Calculate E_frag1(-1) + E_frag2(0)
                    Calculate E_frag1(-2) + E_frag2(+1)?
                    Calculate E_frag1(+1) + E_frag2(-2)?
                Don't limit - just make final charge add to original charge
                Save E_molecule - calculated values associated with bond indices & charges in some data structure
            On failure:
                Track bonds that do not break to yield subgraphs as ring bonds
        Make all possible pairs of ring bonds
        Loop through ring bond pairs and attempt to split into disconnected subgraphs
            Same success/failure procedure as above. Should be wrapped in a function.
        Resolve individual rings
        Attempt to solve for single ring bond dissociation energies, careful with charge

        """

        self.molecule_entry = molecule_entry
        self.fragment_entries = fragment_entries
        self.bond_dissociation_energies = []
        # self.all_bonds = edges_from_babel(target_molecule)
        self.ring_bonds = []
        self.bad_pairs = []
        self.mol_graph = build_MoleculeGraph(Molecule.from_dict(molecule_entry["output"]["optimized_molecule"]))#, self.all_bonds)
        for bond in self.mol_graph.graph.edges: #switch to all_bonds?
            bonds = [(bond[0],bond[1])]
            self.fragment_and_process(bonds)
        self.bond_pairs = []
        for ii,bond in enumerate(self.ring_bonds):
            for jj in range(ii+1,len(self.ring_bonds)):
                bond_pair = [bond, self.ring_bonds[jj]]
                self.bond_pairs += [bond_pair]
        for bond_pair in self.bond_pairs:
            self.fragment_and_process(bond_pair)
        self.solve_ring_bonds()
        # return self.bond_dissociation_energies

    def fragment_and_process(self, bonds):
        try:
            frags = self.mol_graph.split_molecule_subgraphs(bonds,allow_reverse=True)
            frag_success = True
        except RuntimeError:
            if len(bonds) == 1:
                self.ring_bonds += bonds
            elif len(bonds) == 2:
                self.bad_pairs += bonds
            else:
                print('No reason to try and break more than two bonds at once! Exiting...')
                raise ValueError
            frag_success = False
        if frag_success:
            frag1_entries = self.search_fragment_entries(frags[0])[0]
            frag2_entries = self.search_fragment_entries(frags[1])[0]
            for frag1 in frag1_entries:
                for frag2 in frag2_entries:
                    if frag1["calcs_reversed"][-1]["input"]["rem"]["method"] == frag2["calcs_reversed"][-1]["input"]["rem"]["method"] and frag1["calcs_reversed"][-1]["input"]["rem"]["basis"] == frag2["calcs_reversed"][-1]["input"]["rem"]["basis"]: # Add PCM check?
                        if frag1["output"]["initial_molecule"]["charge"] + frag2["output"]["initial_molecule"]["charge"] == self.molecule_entry["output"]["optimized_molecule"]["charge"] and self.molecule_entry["calcs_reversed"][-1]["input"]["rem"]["basis"] == frag1["calcs_reversed"][-1]["input"]["rem"]["basis"] and self.molecule_entry["calcs_reversed"][-1]["input"]["rem"]["method"] == frag1["calcs_reversed"][-1]["input"]["rem"]["method"]:
                            coords = nx.get_node_attributes(self.mol_graph.graph, "coords")
                            specie = nx.get_node_attributes(self.mol_graph.graph, "specie")
                            print(specie[1])
                            print(specie[0])
                            print(bonds)
                            print(bonds[0])
                            print(bonds[0][0])
                            new_entry = [bonds, specie[bonds[0][0]], specie[bonds[0][1]], coords[bonds[0]], coords[bonds[1]], self.molecule_entry["output"]["final_energy"] - (frag1["output"]["final_energy"] + frag2["output"]["final_energy"]), frag1["output"]["final_energy"], frag1["output"]["initial_molecule"]["charge"], frag2["output"]["final_energy"], frag2["output"]["initial_molecule"]["charge"]]
                            self.bond_dissociation_energies += [new_entry]

    def search_fragment_entries(self, frag):
        entries = []
        initial_entries = []
        final_entries = []
        for entry in self.fragment_entries:
            initial_graph = build_MoleculeGraph(Molecule.from_dict(entry["input"]["initial_molecule"])).graph
            final_graph = build_MoleculeGraph(Molecule.from_dict(entry["output"]["initial_molecule"])).graph
            if is_isomorphic(frag.graph, initial_graph) and is_isomorphic(frag.graph, final_graph):
                entries += [entry]
            elif is_isomorphic(frag.graph, initial_graph):
                initial_entries += [entry]
            elif is_isomorphic(frag.graph, final_graph):
                final_entries += [entry]
        return [entries, initial_entries, final_entries]

    def solve_ring_bonds(self):
        pass
<commit_msg>bug fix<commit_after># coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

from __future__ import division, unicode_literals

import re
import csv
import collections
import itertools
from io import open
import math
from six.moves import zip
import logging

from monty.json import MSONable, MontyDecoder

import numpy as np

from pymatgen.core.structure import Molecule
from pymatgen.io.qchem.outputs import edges_from_babel, build_MoleculeGraph, is_isomorphic
import networkx as nx

# have_babel = True
# try:
#     from pymatgen.io.babel import BabelMolAdaptor
#     import openbabel as ob
# except ImportError:
#     print("Cannot find OpenBabel! Thus, bonds must be provided by the user.")
#     have_babel = False

"""
This module defines tools to calculate bond dissocation energies.
"""

__author__ = "Samuel Blau"
__copyright__ = "Copyright 2018, The Materials Project"
__version__ = "1.0"
__maintainer__ = "Samuel Blau"
__email__ = "samblau1@gmail.com"
__status__ = "Alpha"
__date__ = "7/26/18"

logger = logging.getLogger(__name__)

class BondDissociationEnergies(MSONable):

    def __init__(self, molecule_entry, fragment_entries):
        """
        Standard constructor for bond dissociation energies.

        Args:

        Get list of all bonds in target molecule
        Build molecule graph of target molecule
        Loop through bonds aka edges and attempt to split into disconnected subgraphs
            On success:
                Search through fragments: find entries with initial OR final molecules which are isomorphic
                Should be three entires per fragment: original charge, OC+1, OC-1
                If there are too few entries:
                    If one of the fragments is an H atom, you should only find two. H+ should be set (to what value???)
                    If fragment matches initial, but not final structure:
                        Just accept the rearrangement as part of the energetic cost of dissociation?
                        At the very least, flag this structure change in the eventual entry
                    If fragment matches final, but not initial structure:
                        Ignore unless no other fragment matches either?
                    If fragment is unstable:
                        Find its subfragments? Is that even sensical?
                        Just pass?
                    If fragment truly cannot be found, aka has not been calculated or calculate failed to complete:
                        Tell user to calculate it and pass
                If there are too many entries:
                    Get rid of duplicates
                        Going to be annoying given time stamps, rounding errors, etc
                    Remove those whose initial rems don't conform to current defaults - Happens before passing
                    If still more than three, for now, isolate differences, report to user, and grab most recent
                    Just take more negative?
                Grab energies of each fragment at all three charges
                If target molecule is neutral:
                    Calculate E_frag1(0)  + E_frag2(0)
                    Calculate E_frag1(+1) + E_frag2(-1)
                    Calculate E_frag1(-1) + E_frag2(+1)
                If target molecule is +1:
                    Calculate E_frag1(0)  + E_frag2(+1)
                    Calculate E_frag1(+1) + E_frag2(0)
                    Calculate E_frag1(+2) + E_frag2(-1)?
                    Calculate E_frag1(-1) + E_frag2(+2)?
                If target molecule is -1:
                    Calculate E_frag1(0)  + E_frag2(-1)
                    Calculate E_frag1(-1) + E_frag2(0)
                    Calculate E_frag1(-2) + E_frag2(+1)?
                    Calculate E_frag1(+1) + E_frag2(-2)?
                Don't limit - just make final charge add to original charge
                Save E_molecule - calculated values associated with bond indices & charges in some data structure
            On failure:
                Track bonds that do not break to yield subgraphs as ring bonds
        Make all possible pairs of ring bonds
        Loop through ring bond pairs and attempt to split into disconnected subgraphs
            Same success/failure procedure as above. Should be wrapped in a function.
        Resolve individual rings
        Attempt to solve for single ring bond dissociation energies, careful with charge

        """

        self.molecule_entry = molecule_entry
        self.fragment_entries = fragment_entries
        self.bond_dissociation_energies = []
        # self.all_bonds = edges_from_babel(target_molecule)
        self.ring_bonds = []
        self.bad_pairs = []
        self.mol_graph = build_MoleculeGraph(Molecule.from_dict(molecule_entry["output"]["optimized_molecule"]))#, self.all_bonds)
        for bond in self.mol_graph.graph.edges: #switch to all_bonds?
            bonds = [(bond[0],bond[1])]
            self.fragment_and_process(bonds)
        self.bond_pairs = []
        for ii,bond in enumerate(self.ring_bonds):
            for jj in range(ii+1,len(self.ring_bonds)):
                bond_pair = [bond, self.ring_bonds[jj]]
                self.bond_pairs += [bond_pair]
        for bond_pair in self.bond_pairs:
            self.fragment_and_process(bond_pair)
        self.solve_ring_bonds()
        # return self.bond_dissociation_energies

    def fragment_and_process(self, bonds):
        try:
            frags = self.mol_graph.split_molecule_subgraphs(bonds,allow_reverse=True)
            frag_success = True
        except RuntimeError:
            if len(bonds) == 1:
                self.ring_bonds += bonds
            elif len(bonds) == 2:
                self.bad_pairs += bonds
            else:
                print('No reason to try and break more than two bonds at once! Exiting...')
                raise ValueError
            frag_success = False
        if frag_success:
            frag1_entries = self.search_fragment_entries(frags[0])[0]
            frag2_entries = self.search_fragment_entries(frags[1])[0]
            for frag1 in frag1_entries:
                for frag2 in frag2_entries:
                    if frag1["calcs_reversed"][-1]["input"]["rem"]["method"] == frag2["calcs_reversed"][-1]["input"]["rem"]["method"] and frag1["calcs_reversed"][-1]["input"]["rem"]["basis"] == frag2["calcs_reversed"][-1]["input"]["rem"]["basis"]: # Add PCM check?
                        if frag1["output"]["initial_molecule"]["charge"] + frag2["output"]["initial_molecule"]["charge"] == self.molecule_entry["output"]["optimized_molecule"]["charge"] and self.molecule_entry["calcs_reversed"][-1]["input"]["rem"]["basis"] == frag1["calcs_reversed"][-1]["input"]["rem"]["basis"] and self.molecule_entry["calcs_reversed"][-1]["input"]["rem"]["method"] == frag1["calcs_reversed"][-1]["input"]["rem"]["method"]:
                            coords = nx.get_node_attributes(self.mol_graph.graph, "coords")
                            specie = nx.get_node_attributes(self.mol_graph.graph, "specie")
                            new_entry = [bonds, specie[bonds[0][0]], specie[bonds[0][1]], coords[bonds[0][0]], coords[bonds[0][1]], self.molecule_entry["output"]["final_energy"] - (frag1["output"]["final_energy"] + frag2["output"]["final_energy"]), frag1["output"]["final_energy"], frag1["output"]["initial_molecule"]["charge"], frag2["output"]["final_energy"], frag2["output"]["initial_molecule"]["charge"]]
                            self.bond_dissociation_energies += [new_entry]

    def search_fragment_entries(self, frag):
        entries = []
        initial_entries = []
        final_entries = []
        for entry in self.fragment_entries:
            initial_graph = build_MoleculeGraph(Molecule.from_dict(entry["input"]["initial_molecule"])).graph
            final_graph = build_MoleculeGraph(Molecule.from_dict(entry["output"]["initial_molecule"])).graph
            if is_isomorphic(frag.graph, initial_graph) and is_isomorphic(frag.graph, final_graph):
                entries += [entry]
            elif is_isomorphic(frag.graph, initial_graph):
                initial_entries += [entry]
            elif is_isomorphic(frag.graph, final_graph):
                final_entries += [entry]
        return [entries, initial_entries, final_entries]

    def solve_ring_bonds(self):
        pass
<|endoftext|>


<commit_before>import unittest
import requests
from bs4 import BeautifulSoup
from ind_ara_parser import IndAraParser

class pretty_output(object):
    def __init__(self, dict_obj):
        self.dict_obj = dict_obj

    @property
    def header(self):
        return "-= Arti dari {ind_utama} =-".format(
                ind_utama=self.dict_obj.get("utama").get("ind"))

    @property
    def body(self):
        return "{ara_utama}".format(
                ara_utama=self.dict_obj.get("utama").get("ara"))

class PrettyOutputTestCase(unittest.TestCase):
    def setUp(self):
        self.dict_ = {'utama': {"ind": "ind_utama",
                                "ara": "ara_utama",
                                "footer": "footer"},
                      'berhubungan': [
                          {"ind": "ind_pertama",
                           "ara": "ara_pertama"},
                          {"ind": "ind_kedua",
                           "ara": "ara_kedua"}
                          ]
                      }

    def test_pretty_output_header(self):
        po = pretty_output(self.dict_).header
        expected = "-= Arti dari ind_utama =-"
        self.assertEqual(po, expected)

    def test_pretty_output_arabic(self):
        po = pretty_output(self.dict_).body
        expected = "ara_utama"
        self.assertEqual(po, expected)

class Qaamus:

    def terjemah(self, layanan, query):
        """
        Return terjemahan tergantung dengan **layanan** apa yang dia pilih,
        dan **query** apa yang dia pakai.
        Adapun *layanan* di [Qaamus](qaamus.com) saat ini terdapat 3 layanan:
            * Indonesia Arab
            * Angka
            * Terjemah nama
        Sedangkan *query* adalah query pencarian anda"""
        if layanan == "idar":
            url = self.build_idar_url(query)
            soup = self._make_soup(url)
            parser = IndAraParser(soup)
            return {"utama": parser.get_arti_master(),
                    "berhubungan": parser.get_all_arti_berhub(self._make_soup)}

    def _make_soup(self, url):
        """Return BeautifulSoup object."""
        resp = requests.get(url)
        return BeautifulSoup(resp.content)

    def build_idar_url(self, query):
        """Return url pencarian sesuai dengan *query* yang dimasukkan."""
        query = "+".join(query.split(" "))
        url = "http://qaamus.com/indonesia-arab/{query}/1".format(
                query=query)
        return url

class QaamusTest(unittest.TestCase):

    def test_building_idar_url(self):
        q = Qaamus()
        expected_url = "http://qaamus.com/indonesia-arab/capai/1"
        this_url = q.build_idar_url("capai")
        self.assertEqual(this_url, expected_url)

    def test_building_idar_url_with_multiple_words(self):
        q = Qaamus()
        expected_url = "http://qaamus.com/indonesia-arab/mobil+ambulan+bagus/1"
        this_url = q.build_idar_url("mobil ambulan bagus")
        self.assertEqual(this_url, expected_url)

def idar(query):
    return Qaamus().terjemah("idar", query)

if __name__ == "__main__":
    # print(idar("memukul"))
    unittest.main()
<commit_msg>pretty_output().footer 	modified:   qaamus/qaamus.py<commit_after>import unittest
import requests
from bs4 import BeautifulSoup
from ind_ara_parser import IndAraParser

class pretty_output(object):
    def __init__(self, dict_obj):
        self.dict_obj = dict_obj

    @property
    def header(self):
        return "-= Arti dari {ind_utama} =-".format(
                ind_utama=self.dict_obj.get("utama").get("ind"))

    @property
    def body(self):
        return "{ara_utama}".format(
                ara_utama=self.dict_obj.get("utama").get("ara"))

    @property
    def footer(self):
        return "-= {footer} =-".format(
                footer=self.dict_obj.get("utama").get("footer"))

class PrettyOutputTestCase(unittest.TestCase):
    def setUp(self):
        self.dict_ = {'utama': {"ind": "ind_utama",
                                "ara": "ara_utama",
                                "footer": "footer"},
                      'berhubungan': [
                          {"ind": "ind_pertama",
                           "ara": "ara_pertama"},
                          {"ind": "ind_kedua",
                           "ara": "ara_kedua"}
                          ]
                      }

    def test_pretty_output_header(self):
        po = pretty_output(self.dict_).header
        expected = "-= Arti dari ind_utama =-"
        self.assertEqual(po, expected)

    def test_pretty_output_arabic(self):
        po = pretty_output(self.dict_).body
        expected = "ara_utama"
        self.assertEqual(po, expected)

    def test_pretty_output_footer(self):
        po = pretty_output(self.dict_).footer
        expected = "-= footer =-"
        self.assertEqual(po, expected)

class Qaamus:

    def terjemah(self, layanan, query):
        """
        Return terjemahan tergantung dengan **layanan** apa yang dia pilih,
        dan **query** apa yang dia pakai.
        Adapun *layanan* di [Qaamus](qaamus.com) saat ini terdapat 3 layanan:
            * Indonesia Arab
            * Angka
            * Terjemah nama
        Sedangkan *query* adalah query pencarian anda"""
        if layanan == "idar":
            url = self.build_idar_url(query)
            soup = self._make_soup(url)
            parser = IndAraParser(soup)
            return {"utama": parser.get_arti_master(),
                    "berhubungan": parser.get_all_arti_berhub(self._make_soup)}

    def _make_soup(self, url):
        """Return BeautifulSoup object."""
        resp = requests.get(url)
        return BeautifulSoup(resp.content)

    def build_idar_url(self, query):
        """Return url pencarian sesuai dengan *query* yang dimasukkan."""
        query = "+".join(query.split(" "))
        url = "http://qaamus.com/indonesia-arab/{query}/1".format(
                query=query)
        return url

class QaamusTest(unittest.TestCase):

    def test_building_idar_url(self):
        q = Qaamus()
        expected_url = "http://qaamus.com/indonesia-arab/capai/1"
        this_url = q.build_idar_url("capai")
        self.assertEqual(this_url, expected_url)

    def test_building_idar_url_with_multiple_words(self):
        q = Qaamus()
        expected_url = "http://qaamus.com/indonesia-arab/mobil+ambulan+bagus/1"
        this_url = q.build_idar_url("mobil ambulan bagus")
        self.assertEqual(this_url, expected_url)

def idar(query):
    return Qaamus().terjemah("idar", query)

if __name__ == "__main__":
    # print(idar("memukul"))
    unittest.main()
<|endoftext|>


<commit_before>'''
Module to deal with prior range
'''
import numpy as np

def PriorRange(prior_name , Mr):
    ''' Given prior dictionary name, return the prior range.
    '''
    if prior_name is None:
        prior_name = 'first_try'

    dict_table = prior_dict_table(Mr)

    prior_dict = dict_table[prior_name]

    prior_min = prior_dict['prior_min']
    prior_max = prior_dict['prior_max']
    return [prior_min, prior_max]

def prior_dict_table(Mr):
    ''' dictionary table of priors
    '''
    if Mr ==21. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 13., -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }

    if Mr ==20.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 12., -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==20. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 12., -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==19.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==19. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }

    if Mr ==18.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==18. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    return dict_table
<commit_msg>updated prior<commit_after>'''
Module to deal with prior range
'''
import numpy as np

def PriorRange(prior_name , Mr):
    ''' Given prior dictionary name, return the prior range.
    '''
    if prior_name is None:
        prior_name = 'first_try'

    dict_table = prior_dict_table(Mr)

    prior_dict = dict_table[prior_name]

    prior_min = prior_dict['prior_min']
    prior_max = prior_dict['prior_max']
    return [prior_min, prior_max]

def prior_dict_table(Mr):
    ''' dictionary table of priors
    '''
    if Mr ==21. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }

    if Mr ==20.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==20. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14., 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==19.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10., 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==19. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }

    if Mr ==18.5 :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    if Mr ==18. :
      dict_table = {
            'first_try': {
                'prior_min': [10., 0.05, 10.0, 0.85, 11.5, -1. , -1.],
                'prior_max': [14.5, 1.5, 14.0, 1.45, 15., 1. , 1.]
                }
              }
    return dict_table
<|endoftext|>


<commit_before><commit_msg>factor out helper to prepare clip paths for bool op<commit_after><|endoftext|>