<commit_before># coding=utf-8
#
# Copyright 2017 F5 Networks Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Wrapper functions for custom-profile mgmt via the f5-sdk"""

import logging
import os

LOGGER = logging.getLogger(__name__)

def create_client_ssl_profile(mgmt, partition, profile):
    """Create a Client SSL Profile."""
    ssl_client_profile = mgmt.tm.ltm.profile.client_ssls.client_ssl
    incomplete = 0

    name = profile['name']

    # No need to create if it exists
    if ssl_client_profile.exists(name=name, partition=partition):
        return 0

    cert = profile['cert']
    cert_name = name + '.crt'
    if cert != "":
        incomplete = _install_certificate(mgmt, cert, cert_name)
    if incomplete > 0:
        # Unable to install cert
        return incomplete

    key = profile['key']
    key_name = name + '.key'
    if key != "":
        incomplete = _install_key(mgmt, key, key_name)
    if incomplete > 0:
        # Unable to install key
        return incomplete

    try:
        # create ssl-client profile from cert/key pair
        serverName = profile.get('serverName', None)
        sniDefault = profile.get('sniDefault', False)
        kwargs = {}
        if cert != "" and key != "":
            chain = [{'name': name,
                      'cert': '/Common/' + cert_name,
                      'key': '/Common/' + key_name}]
            kwargs = {'certKeyChain': chain}

        ssl_client_profile.create(name=name,
                                  partition=partition,
                                  serverName=serverName,
                                  sniDefault=sniDefault,
                                  defaultsFrom=None,
                                  **kwargs)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error creating client SSL profile: %s", str(err))
        incomplete = 1

    return incomplete

def create_server_ssl_profile(mgmt, partition, profile):
    """Create a Server SSL Profile."""
    ssl_server_profile = mgmt.tm.ltm.profile.server_ssls.server_ssl
    incomplete = 0

    name = profile['name']

    # No need to create if it exists
    if ssl_server_profile.exists(name=name, partition=partition):
        return 0

    cert = profile['cert']
    cert_name = name + '.crt'
    if cert != "":
        incomplete = _install_certificate(mgmt, cert, cert_name)
    if incomplete > 0:
        # Unable to install cert
        return incomplete

    try:
        # create ssl-server profile
        serverName = profile.get('serverName', None)
        sniDefault = profile.get('sniDefault', False)
        kwargs = {}
        if cert != "":
            kwargs = {'chain': cert_name}

        ssl_server_profile.create(name=name,
                                  partition=partition,
                                  serverName=serverName,
                                  sniDefault=sniDefault,
                                  **kwargs)
    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error creating server SSL profile: %s", str(err))

    return incomplete

def delete_unused_ssl_profiles(mgmt, partition, config):
    """Delete unused SSL Profiles."""
    incomplete = 0

    # client profiles
    try:
        client_profiles = mgmt.tm.ltm.profile.client_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, client_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading client SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    # server profiles
    try:
        server_profiles = mgmt.tm.ltm.profile.server_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, server_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading server SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    return incomplete

def _delete_ssl_profiles(config, profiles):
    incomplete = 0

    if 'customProfiles' not in config:
        # delete any profiles in managed partition
        for prof in profiles:
            try:
                prof.delete()
            except Exception as err:  # pylint: disable=broad-except
                LOGGER.error("Error deleting SSL profile: %s", str(err))
                incomplete += 1
    else:
        # delete profiles no longer in our config
        for prof in profiles:
            if not any(d['name'] == prof.name
                       for d in config['customProfiles']):
                try:
                    prof.delete()
                except Exception as err:  # pylint: disable=broad-except
                    LOGGER.error("Error deleting SSL profile: %s", str(err))
                    incomplete += 1

    return incomplete

def _upload_crypto_file(mgmt, file_data, file_name):
    # bigip object is of type f5.bigip.tm;
    # we need f5.bigip.shared for the uploader
    uploader = mgmt.shared.file_transfer.uploads

    # In-memory upload -- data not written to local file system but
    # is saved as a file on the BIG-IP
    uploader.upload_bytes(file_data, file_name)

def _import_certificate(mgmt, cert_name):
    cert_registrar = mgmt.tm.sys.crypto.certs
    param_set = {}
    param_set['name'] = cert_name
    param_set['from-local-file'] = os.path.join(
        '/var/config/rest/downloads', cert_name)
    cert_registrar.exec_cmd('install', **param_set)

def _import_key(mgmt, key_name):
    key_registrar = mgmt.tm.sys.crypto.keys
    param_set = {}
    param_set['name'] = key_name
    param_set['from-local-file'] = os.path.join(
        '/var/config/rest/downloads', key_name)
    key_registrar.exec_cmd('install', **param_set)

def _install_certificate(mgmt, cert_data, cert_name):
    incomplete = 0

    try:
        if not _certificate_exists(mgmt, cert_name):
            # Upload and install cert
            _upload_crypto_file(mgmt, cert_data, cert_name)
            _import_certificate(mgmt, cert_name)

    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error uploading certificate %s: %s", cert_name, str(err))

    return incomplete

def _install_key(mgmt, key_data, key_name):
    incomplete = 0

    try:
        if not _key_exists(mgmt, key_name):
            # Upload and install cert
            _upload_crypto_file(mgmt, key_data, key_name)
            _import_key(mgmt, key_name)

    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error uploading key %s: %s", key_name, str(err))

    return incomplete

def _certificate_exists(mgmt, cert_name):
    # All certs are in the Common partition
    name_to_find = "/Common/{}".format(cert_name)
    for cert in mgmt.tm.sys.crypto.certs.get_collection():
        if cert.name == name_to_find:
            return True
    return False

def _key_exists(mgmt, key_name):
    # All keys are in the Common partition
    name_to_find = "/Common/{}".format(key_name)
    for key in mgmt.tm.sys.crypto.keys.get_collection():
        if key.name == name_to_find:
            return True
    return False

def _delete_unused_ssl_profiles(mgmt, partition, config):
    incomplete = 0

    # client profiles
    try:
        client_profiles = mgmt.tm.ltm.profile.client_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, client_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading client SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    # server profiles
    try:
        server_profiles = mgmt.tm.ltm.profile.server_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, server_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading server SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    return incomplete
<commit_msg>Issue 163: Configure Server SSL Profile to validate server certificates<commit_after># coding=utf-8
#
# Copyright 2017 F5 Networks Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Wrapper functions for custom-profile mgmt via the f5-sdk"""

import logging
import os

LOGGER = logging.getLogger(__name__)

def create_client_ssl_profile(mgmt, partition, profile):
    """Create a Client SSL Profile."""
    ssl_client_profile = mgmt.tm.ltm.profile.client_ssls.client_ssl
    incomplete = 0

    name = profile['name']

    # No need to create if it exists
    if ssl_client_profile.exists(name=name, partition=partition):
        return 0

    cert = profile['cert']
    cert_name = name + '.crt'
    if cert != "":
        incomplete = _install_certificate(mgmt, cert, cert_name)
    if incomplete > 0:
        # Unable to install cert
        return incomplete

    key = profile['key']
    key_name = name + '.key'
    if key != "":
        incomplete = _install_key(mgmt, key, key_name)
    if incomplete > 0:
        # Unable to install key
        return incomplete

    try:
        # create ssl-client profile from cert/key pair
        serverName = profile.get('serverName', None)
        sniDefault = profile.get('sniDefault', False)
        kwargs = {}
        if cert != "" and key != "":
            chain = [{'name': name,
                      'cert': '/Common/' + cert_name,
                      'key': '/Common/' + key_name}]
            kwargs = {'certKeyChain': chain}

        ssl_client_profile.create(name=name,
                                  partition=partition,
                                  serverName=serverName,
                                  sniDefault=sniDefault,
                                  defaultsFrom=None,
                                  **kwargs)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error creating client SSL profile: %s", str(err))
        incomplete = 1

    return incomplete

def create_server_ssl_profile(mgmt, partition, profile):
    """Create a Server SSL Profile."""
    ssl_server_profile = mgmt.tm.ltm.profile.server_ssls.server_ssl
    incomplete = 0

    name = profile['name']

    # No need to create if it exists
    if ssl_server_profile.exists(name=name, partition=partition):
        return 0

    cert = profile['cert']
    cert_name = name + '.crt'
    if cert != "":
        incomplete = _install_certificate(mgmt, cert, cert_name)
    if incomplete > 0:
        # Unable to install cert
        return incomplete

    try:
        # create ssl-server profile
        serverName = profile.get('serverName', None)
        sniDefault = profile.get('sniDefault', False)
        peerCertMode = profile.get('peerCertMode', 'ignore')
        kwargs = {}
        if cert != "":
            kwargs = {'chain': cert_name}

        ssl_server_profile.create(name=name,
                                  partition=partition,
                                  serverName=serverName,
                                  sniDefault=sniDefault,
                                  peerCertMode=peerCertMode,
                                  **kwargs)
    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error creating server SSL profile: %s", str(err))

    return incomplete

def delete_unused_ssl_profiles(mgmt, partition, config):
    """Delete unused SSL Profiles."""
    incomplete = 0

    # client profiles
    try:
        client_profiles = mgmt.tm.ltm.profile.client_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, client_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading client SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    # server profiles
    try:
        server_profiles = mgmt.tm.ltm.profile.server_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, server_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading server SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    return incomplete

def _delete_ssl_profiles(config, profiles):
    incomplete = 0

    if 'customProfiles' not in config:
        # delete any profiles in managed partition
        for prof in profiles:
            try:
                prof.delete()
            except Exception as err:  # pylint: disable=broad-except
                LOGGER.error("Error deleting SSL profile: %s", str(err))
                incomplete += 1
    else:
        # delete profiles no longer in our config
        for prof in profiles:
            if not any(d['name'] == prof.name
                       for d in config['customProfiles']):
                try:
                    prof.delete()
                except Exception as err:  # pylint: disable=broad-except
                    LOGGER.error("Error deleting SSL profile: %s", str(err))
                    incomplete += 1

    return incomplete

def _upload_crypto_file(mgmt, file_data, file_name):
    # bigip object is of type f5.bigip.tm;
    # we need f5.bigip.shared for the uploader
    uploader = mgmt.shared.file_transfer.uploads

    # In-memory upload -- data not written to local file system but
    # is saved as a file on the BIG-IP
    uploader.upload_bytes(file_data, file_name)

def _import_certificate(mgmt, cert_name):
    cert_registrar = mgmt.tm.sys.crypto.certs
    param_set = {}
    param_set['name'] = cert_name
    param_set['from-local-file'] = os.path.join(
        '/var/config/rest/downloads', cert_name)
    cert_registrar.exec_cmd('install', **param_set)

def _import_key(mgmt, key_name):
    key_registrar = mgmt.tm.sys.crypto.keys
    param_set = {}
    param_set['name'] = key_name
    param_set['from-local-file'] = os.path.join(
        '/var/config/rest/downloads', key_name)
    key_registrar.exec_cmd('install', **param_set)

def _install_certificate(mgmt, cert_data, cert_name):
    incomplete = 0

    try:
        if not _certificate_exists(mgmt, cert_name):
            # Upload and install cert
            _upload_crypto_file(mgmt, cert_data, cert_name)
            _import_certificate(mgmt, cert_name)

    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error uploading certificate %s: %s", cert_name, str(err))

    return incomplete

def _install_key(mgmt, key_data, key_name):
    incomplete = 0

    try:
        if not _key_exists(mgmt, key_name):
            # Upload and install cert
            _upload_crypto_file(mgmt, key_data, key_name)
            _import_key(mgmt, key_name)

    except Exception as err:  # pylint: disable=broad-except
        incomplete += 1
        LOGGER.error("Error uploading key %s: %s", key_name, str(err))

    return incomplete

def _certificate_exists(mgmt, cert_name):
    # All certs are in the Common partition
    name_to_find = "/Common/{}".format(cert_name)
    for cert in mgmt.tm.sys.crypto.certs.get_collection():
        if cert.name == name_to_find:
            return True
    return False

def _key_exists(mgmt, key_name):
    # All keys are in the Common partition
    name_to_find = "/Common/{}".format(key_name)
    for key in mgmt.tm.sys.crypto.keys.get_collection():
        if key.name == name_to_find:
            return True
    return False

def _delete_unused_ssl_profiles(mgmt, partition, config):
    incomplete = 0

    # client profiles
    try:
        client_profiles = mgmt.tm.ltm.profile.client_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, client_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading client SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    # server profiles
    try:
        server_profiles = mgmt.tm.ltm.profile.server_ssls.get_collection(
            requests_params={'params': '$filter=partition+eq+%s' % partition})
        incomplete += _delete_ssl_profiles(config, server_profiles)
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error("Error reading server SSL profiles from BIG-IP: %s",
                     str(err))
        incomplete += 1

    return incomplete
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

#
#
#  Copyright 2013 Netflix, Inc.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#
#

"""
aminator
========
Create images from packages for deployment in various cloud formations
"""
import logging
try:
    from logging import NullHandler
except ImportError:
    # py26
    try:
        from logutils import NullHandler
    except ImportError:
        class NullHandler(logging.Handler):
            def emit(self, record):
                pass

__version__ = '2.1.83.dev'
__versioninfo__ = __version__.split('.')
__all__ = ()

logging.getLogger(__name__).addHandler(NullHandler())
<commit_msg>update release to 2.1.84.dev<commit_after># -*- coding: utf-8 -*-

#
#
#  Copyright 2013 Netflix, Inc.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#
#

"""
aminator
========
Create images from packages for deployment in various cloud formations
"""
import logging
try:
    from logging import NullHandler
except ImportError:
    # py26
    try:
        from logutils import NullHandler
    except ImportError:
        class NullHandler(logging.Handler):
            def emit(self, record):
                pass

__version__ = '2.1.84.dev'
__versioninfo__ = __version__.split('.')
__all__ = ()

logging.getLogger(__name__).addHandler(NullHandler())
<|endoftext|>


<commit_before>from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist

def smart_fqdn_exists(fqdn, *args, **kwargs):
    """
    Searching for a fqdn by actually looking at a fqdn is very inefficient.
    Instead we should:
        1) Look for a domain with the name of fqdn.
        2) Look for a label = fqdn.split('.')[0]
            and domain = fqdn.split('.')[1:]
    """
    from cyder.cydns.domain.models import Domain

    # Try approach 1
    try:
        search_domain = Domain.objects.get(name=fqdn)
        label = ''
    except ObjectDoesNotExist:
        search_domain = None
    if search_domain:
        for type_, qset in _build_label_domain_queries(
                label, search_domain, **kwargs):
            if qset.exists():
                return qset

    # Try approach 2
    search_domain = None
    if len(fqdn.split('.')) == 1:
        return None
    try:
        label = fqdn.split('.')[0]
        domain_name = '.'.join(fqdn.split('.')[1:])
        search_domain = Domain.objects.get(
            name=domain_name)
    except ObjectDoesNotExist:
        search_domain = None
    if search_domain:
        for type_, qset in _build_label_domain_queries(
                label, search_domain, **kwargs):
            if qset.exists():
                return qset

def _build_label_domain_queries(label, domain, mx=True, sr=True, tx=True,
                                cn=True, ar=True, intr=True, ns=True, ss=True):
    # We import this way to make it easier to import this file without
    # getting cyclic imports.
    qsets = []
    if mx:
        from cyder.cydns.mx.models import MX
        qsets.append(('MX', MX.objects.
                      filter(**{'label': label, 'domain': domain})))
    if ns:
        if label == '':
            from cyder.cydns.nameserver.models import Nameserver
            qsets.append(('NS', Nameserver.objects.
                          filter(**{'domain': domain})))
    if sr:
        from cyder.cydns.srv.models import SRV
        qsets.append(('SRV', SRV.objects.
                      filter(**{'label': label, 'domain': domain})))
    if tx:
        from cyder.cydns.txt.models import TXT
        qsets.append(('TXT', TXT.objects.
                      filter(**{'label': label, 'domain': domain})))
    if ss:
        from cyder.cydns.sshfp.models import SSHFP
        qsets.append(('SSHFP', SSHFP.objects.
                      filter(**{'label': label, 'domain': domain})))
    if cn:
        from cyder.cydns.cname.models import CNAME
        qsets.append(('CNAME', CNAME.objects.
                      filter(**{'label': label, 'domain': domain})))
    if ar:
        from cyder.cydns.address_record.models import AddressRecord
        ars = AddressRecord.objects.filter(
            **{'label': label, 'domain': domain})
        qsets.append(('AddressRecord', ars))
    if intr:
        from cyder.cydhcp.interface.static_intr.models import StaticInterface
        intrs = StaticInterface.objects.filter(
            **{'label': label, 'domain': domain})
        qsets.append(('AddressRecord', intrs))

    return qsets
<commit_msg>Clean up some stuff while I'm at it<commit_after>from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist

def smart_fqdn_exists(fqdn, *args, **kwargs):
    """
    Searching for a fqdn by actually looking at a fqdn is very inefficient.
    Instead we should:
        1) Look for a domain with the name of fqdn.
        2) Look for a label = fqdn.split('.')[0]
            and domain = fqdn.split('.')[1:]
    """
    from cyder.cydns.domain.models import Domain

    # Try approach 1
    try:
        search_domain = Domain.objects.get(name=fqdn)
        label = ''
    except ObjectDoesNotExist:
        search_domain = None
    if search_domain:
        for type_, qset in _build_label_domain_queries(
                label, search_domain, **kwargs):
            if qset.exists():
                return qset

    # Try approach 2
    search_domain = None
    if len(fqdn.split('.')) == 1:
        return None
    try:
        label = fqdn.split('.')[0]
        domain_name = '.'.join(fqdn.split('.')[1:])
        search_domain = Domain.objects.get(
            name=domain_name)
    except ObjectDoesNotExist:
        search_domain = None
    if search_domain:
        for type_, qset in _build_label_domain_queries(
                label, search_domain, **kwargs):
            if qset.exists():
                return qset

def _build_label_domain_queries(label, domain, mx=True, sr=True, tx=True,
                                cn=True, ar=True, intr=True, ns=True, ss=True):
    # We import this way to make it easier to import this file without
    # getting cyclic imports.
    qsets = []
    if mx:
        from cyder.cydns.mx.models import MX
        qsets.append(('MX', MX.objects.
                      filter(label=label, domain=domain)))
    if ns:
        if label == '':
            from cyder.cydns.nameserver.models import Nameserver
            qsets.append(('NS', Nameserver.objects.
                          filter(domain=domain)))
    if sr:
        from cyder.cydns.srv.models import SRV
        qsets.append(('SRV', SRV.objects.
                      filter(label=label, domain=domain)))
    if tx:
        from cyder.cydns.txt.models import TXT
        qsets.append(('TXT', TXT.objects.
                      filter(label=label, domain=domain)))
    if ss:
        from cyder.cydns.sshfp.models import SSHFP
        qsets.append(('SSHFP', SSHFP.objects.
                      filter(label=label, domain=domain)))
    if cn:
        from cyder.cydns.cname.models import CNAME
        qsets.append(('CNAME', CNAME.objects.
                      filter(label=label, domain=domain)))
    if ar:
        from cyder.cydns.address_record.models import AddressRecord
        ars = AddressRecord.objects.filter(label=label, domain=domain)
        qsets.append(('AddressRecord', ars))
    if intr:
        from cyder.cydhcp.interface.static_intr.models import StaticInterface
        intrs = StaticInterface.objects.filter(label=label, domain=domain)
        qsets.append(('AddressRecord', intrs))

    return qsets
<|endoftext|>


<commit_before>import os
import web

import simplejson

from rctk.sessions import Manager, Session, SpawnedSession

class WebPyGateway(object):
    """ A gateway mediates between user/browser and RCTK application.
        This gateway is built on the web.py application server """
    def __init__(self, manager, use_cookies=False):
        self.manager = manager
        self.use_cookies = use_cookies

    def GET(self, data):
        data = data.strip()
        session = None

        # FIXME: this is an hack to get spawned sessions to work,
        # /favicon.ico should be added to the resource manager
        if data == '/favicon.ico':
            raise web.notfound()

        if self.use_cookies:
            session = self.get_session_from_cookie()
            rest = data
        else:
            if data:
                sessionid, rest = data.split('/', 1)
                session = self.manager.get(sessionid)

        if session is None:
            sessionid = self.manager.create()
            if self.use_cookies:
                web.setcookie('rctk-sid', sessionid)
                web.seeother('/')
            else:
                web.seeother('/' + sessionid + '/')
            return

        type, result = session.serve(rest)
        web.header("content-type", type)
        self.manager.cleanup_expired()
        return result

    def POST(self, data):
        data = data.strip()
        session = None

        if self.use_cookies:
            session = self.get_session_from_cookie()
            rest = data
        else:
            sessionid, rest = data.split('/', 1)
            session = self.manager.get(sessionid)

        if session is None:
            web.seeother('/')
            return

        web.header("content-type", "application/json")
        method = rest.strip()
        arguments = web.input()

        self.manager.cleanup_expired()
        try:
            result = session.handle(method, **arguments)
            return simplejson.dumps(result)
        except:
            # TODO: something has gone wrong, find out what and handle session cleanup or recovery.
            pass

    def get_session_from_cookie(self):
        """ Use a cookie to find out if the client already has an active session.
            Returns the session or None if valid session is found.
        """
        sessionid = web.cookies().get('rctk-sid')
        if sessionid:
            session = self.manager.get(sessionid)
            if session is None:
                # user has a cookie, but no session present so delete the cookie
                web.setcookie('rctk-sid', sessionid, expires=-84000)
            else:
                return session
        return None

    def __call__(self):
        """
            web.py creates new instances of the class on each
            request. We don't want that, so in stead we pretend
            to create a new instance, but actually just
            return self
        """
        return self

def app(manager, use_cookies=False):
    ## required for local static to work
    os.chdir(os.path.dirname(__file__))
    gw = WebPyGateway(manager, use_cookies=use_cookies)
    return web.application(('/(.*)', 'gateway'), {'gateway':gw}, autoreload=True)

def serve(manager=Manager, use_cookies=False):
    """ create the (webpy) app and run it """
    app(manager, use_cookies=use_cookies).run()

<commit_msg>oops, committed to quickly<commit_after>import os
import web

import simplejson

from rctk.sessions import Manager, Session, SpawnedSession

class WebPyGateway(object):
    """ A gateway mediates between user/browser and RCTK application.
        This gateway is built on the web.py application server """
    def __init__(self, manager, use_cookies=False):
        self.manager = manager
        self.use_cookies = use_cookies

    def GET(self, data):
        data = data.strip()
        session = None

        # FIXME: this is an hack to get spawned sessions to work,
        # /favicon.ico should be added to the resource manager
        if data == 'favicon.ico':
            raise web.notfound()

        if self.use_cookies:
            session = self.get_session_from_cookie()
            rest = data
        else:
            if data:
                sessionid, rest = data.split('/', 1)
                session = self.manager.get(sessionid)

        if session is None:
            sessionid = self.manager.create()
            if self.use_cookies:
                web.setcookie('rctk-sid', sessionid)
                web.seeother('/')
            else:
                web.seeother('/' + sessionid + '/')
            return

        type, result = session.serve(rest)
        web.header("content-type", type)
        self.manager.cleanup_expired()
        return result

    def POST(self, data):
        data = data.strip()
        session = None

        if self.use_cookies:
            session = self.get_session_from_cookie()
            rest = data
        else:
            sessionid, rest = data.split('/', 1)
            session = self.manager.get(sessionid)

        if session is None:
            web.seeother('/')
            return

        web.header("content-type", "application/json")
        method = rest.strip()
        arguments = web.input()

        self.manager.cleanup_expired()
        try:
            result = session.handle(method, **arguments)
            return simplejson.dumps(result)
        except:
            # TODO: something has gone wrong, find out what and handle session cleanup or recovery.
            pass

    def get_session_from_cookie(self):
        """ Use a cookie to find out if the client already has an active session.
            Returns the session or None if valid session is found.
        """
        sessionid = web.cookies().get('rctk-sid')
        if sessionid:
            session = self.manager.get(sessionid)
            if session is None:
                # user has a cookie, but no session present so delete the cookie
                web.setcookie('rctk-sid', sessionid, expires=-84000)
            else:
                return session
        return None

    def __call__(self):
        """
            web.py creates new instances of the class on each
            request. We don't want that, so in stead we pretend
            to create a new instance, but actually just
            return self
        """
        return self

def app(manager, use_cookies=False):
    ## required for local static to work
    os.chdir(os.path.dirname(__file__))
    gw = WebPyGateway(manager, use_cookies=use_cookies)
    return web.application(('/(.*)', 'gateway'), {'gateway':gw}, autoreload=True)

def serve(manager=Manager, use_cookies=False):
    """ create the (webpy) app and run it """
    app(manager, use_cookies=use_cookies).run()

<|endoftext|>


<commit_before>import os

def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:
        import errno
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise
<commit_msg>Fix another style issue<commit_after>import os

def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:
        import errno
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise
<|endoftext|>


<commit_before># emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""reST directive for syntax-highlighting ipython interactive sessions.
"""

#-----------------------------------------------------------------------------
# Needed modules

# Standard library
import re

# Third party
from pygments.lexer import Lexer, do_insertions
from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer,
                                   PythonTracebackLexer)
from pygments.token import Comment, Generic

from sphinx import highlighting

#-----------------------------------------------------------------------------
# Global constants
line_re = re.compile('.*?\n')

#-----------------------------------------------------------------------------
# Code begins - classes and functions

class IPythonConsoleLexer(Lexer):
    """
    For IPython console output or doctests, such as:

    .. sourcecode:: ipython

      In [1]: a = 'foo'

      In [2]: a
      Out[2]: 'foo'

      In [3]: print a
      foo

      In [4]: 1 / 0

    Notes:

      - Tracebacks are not currently supported.

      - It assumes the default IPython prompts, not customized ones.
    """

    name = 'IPython console session'
    aliases = ['ipython']
    mimetypes = ['text/x-ipython-console']
    input_prompt = re.compile("(In \[[0-9]+\]: )|(   \.\.\.+:)")
    output_prompt = re.compile("(Out\[[0-9]+\]: )|(   \.\.\.+:)")
    continue_prompt = re.compile("   \.\.\.+:")
    tb_start = re.compile("\-+")

    def get_tokens_unprocessed(self, text):
        pylexer = PythonLexer(**self.options)
        tblexer = PythonTracebackLexer(**self.options)

        curcode = ''
        insertions = []
        for match in line_re.finditer(text):
            line = match.group()
            input_prompt = self.input_prompt.match(line)
            continue_prompt = self.continue_prompt.match(line.rstrip())
            output_prompt = self.output_prompt.match(line)
            if line.startswith("#"):
                insertions.append((len(curcode),
                                   [(0, Comment, line)]))
            elif input_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Prompt, input_prompt.group())]))
                curcode += line[input_prompt.end():]
            elif continue_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Prompt, continue_prompt.group())]))
                curcode += line[continue_prompt.end():]
            elif output_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Output, output_prompt.group())]))
                curcode += line[output_prompt.end():]
            else:
                if curcode:
                    for item in do_insertions(insertions,
                                              pylexer.get_tokens_unprocessed(curcode)):
                        yield item
                        curcode = ''
                        insertions = []
                yield match.start(), Generic.Output, line
        if curcode:
            for item in do_insertions(insertions,
                                      pylexer.get_tokens_unprocessed(curcode)):
                yield item

#-----------------------------------------------------------------------------
# Register the extension as a valid pygments lexer
highlighting.lexers['ipython'] = IPythonConsoleLexer()
<commit_msg>ipython highlighting extension is now a proper sphinx extension<commit_after># emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""reST directive for syntax-highlighting ipython interactive sessions.
"""

#-----------------------------------------------------------------------------
# Needed modules

# Standard library
import re

# Third party
from pygments.lexer import Lexer, do_insertions
from pygments.lexers.agile import (PythonLexer)
from pygments.token import Comment, Generic

#-----------------------------------------------------------------------------
# Global constants
line_re = re.compile('.*?\n')

#-----------------------------------------------------------------------------
# Code begins - classes and functions

class IPythonConsoleLexer(Lexer):
    """
    For IPython console output or doctests, such as:

    .. sourcecode:: ipython

      In [1]: a = 'foo'

      In [2]: a
      Out[2]: 'foo'

      In [3]: print a
      foo

      In [4]: 1 / 0

    Notes:

      - Tracebacks are not currently supported.

      - It assumes the default IPython prompts, not customized ones.
    """

    name = 'IPython console session'
    aliases = ['ipython']
    mimetypes = ['text/x-ipython-console']
    input_prompt = re.compile("(In \[[0-9]+\]: )|(   \.\.\.+:)")
    output_prompt = re.compile("(Out\[[0-9]+\]: )|(   \.\.\.+:)")
    continue_prompt = re.compile("   \.\.\.+:")
    tb_start = re.compile("\-+")

    def get_tokens_unprocessed(self, text):
        pylexer = PythonLexer(**self.options)

        curcode = ''
        insertions = []
        for match in line_re.finditer(text):
            line = match.group()
            input_prompt = self.input_prompt.match(line)
            continue_prompt = self.continue_prompt.match(line.rstrip())
            output_prompt = self.output_prompt.match(line)
            if line.startswith("#"):
                insertions.append((len(curcode),
                                   [(0, Comment, line)]))
            elif input_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Prompt, input_prompt.group())]))
                curcode += line[input_prompt.end():]
            elif continue_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Prompt, continue_prompt.group())]))
                curcode += line[continue_prompt.end():]
            elif output_prompt is not None:
                insertions.append((len(curcode),
                                   [(0, Generic.Output, output_prompt.group())]))
                curcode += line[output_prompt.end():]
            else:
                if curcode:
                    for item in do_insertions(insertions,
                                              pylexer.get_tokens_unprocessed(curcode)):
                        yield item
                        curcode = ''
                        insertions = []
                yield match.start(), Generic.Output, line
        if curcode:
            for item in do_insertions(insertions,
                                      pylexer.get_tokens_unprocessed(curcode)):
                yield item
def setup(app):
    app.add_lexer('ipython', IPythonConsoleLexer())
<|endoftext|>


<commit_before># Copyright (c) 2006 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

# State Constants
BITS_LOOSE=0      # Bits object not yet associated with a BitBucket object
BITS_NEED_READ=1  # data in the Bits object needs to be read from S3
BITS_NEED_WRITE=2 # data in the Bits object needs to be written to S3
BITS_IN_SYNC=3    # data in the Bits object is consistent with S3

class Bits:

    def __init__(self, filename=None):
        self.state = BITS_LOOSE
        self.metadata = {}
        self.bucket = None
        self.content_type = 'application/octet-stream'
        self.filename = filename
        self.etag = None
        self.key = None
        self.last_modified = None
        self.owner = None
        self.storage_class = None

    def __getattr__(self, name):
        if name == 'data':
            if self.state == BITS_NEED_READ:
                if self.bucket:
                    self.bucket.get_bits(self)
            return self._data
        elif name in self.metadata:
            return self.metadata[name]
        else:
            raise AttributeError

    def __setattr__(self, name, value):
        if name == 'data':
            self._data = value
            if value:
                self.__dict__['size'] = len(value)
            if self.bucket:
                self.bucket.send_bits(self)
        elif name == 'filename':
            self.__dict__[name] = value
            if value:
                self.sync()
        else:
            self.__dict__[name] = value

    def __getitem__(self, key):
        return self.metadata[key]

    def __setitem__(self, key, value):
        self.metadata[key] = value

    def __delitem__(self, key):
        del self.metadata[key]

    def _compute_md5(self):
        m = md5.new()
        p = open(self.filename, 'rb')
        s = p.read(8192)
        while s:
            m.update(s)
            s = p.read(8192)
        self.md5 = '"%s"' % m.hexdigest()
        p.close()

    def sync(self):
        if self.filename:
            if os.path.exists(self.filename):
                self.size = os.stat(self.filename).st_size
                self._compute_md5()
                self.content_type = mimetypes.guess_type(self.filename)[0]
                filter_bits(self)
                self.state = BITS_NEED_WRITE
                if self.bucket:
                    self.bucket.send_file(self)
            else:
                self.state = BITS_NEED_READ
                if self.bucket:
                    self.bucket.get_file(self, self.filename)
        else:
            self.state = BITS_NEED_WRITE
            self.bucket.send_bits(self)

    def get_url(self, expires_in=60):
        if self.bucket:
            return self.bucket.generate_url('get', self, expires_in)
        else:
            raise BitBucketError("Bits aren't associated with a BitBucket yet")

    def delete_url(self, expires_in=60):
        if self.bucket:
            return self.bucket.generate_url('delete', self, expires_in)
        else:
            raise BitBucketError("Bits aren't associated with a BitBucket yet")

    def set_canned_acl(self, policy):
        if policy not in _canned_access_policies:
            raise BitBucketError('Invalid acl_policy: %s' % policy)
        self.bucket.connection.set_canned_acl(self, policy)

    def get_acl(self, headers={}):
        path = '/%s/%s?acl' % (self.bucket.name,
                               urllib.quote.quote_plus(self.key))
        response = self.make_request('GET', path, headers)
        return response.read()

    def to_file(self, filename):
        if self.bucket != None:
            self.bucket.get_file(self, filename)
        else:
            raise BitBucketError("Bits aren't associated with a BitBucket yet")

<commit_msg>Removed bits.py.  Not needed.<commit_after><|endoftext|>


<commit_before># encoding: utf-8
# Fabmanager decorators

from fabric.api import *

# These variables must be defined at the actual fabfile.py
# Address of the proxy server intermediating the executation
env.proxy_server = ''

# Location, at the proxy server, where fabfily.py will reside
env.proxy_home = ''

# List of hosts and/or roles specified for this session - will
# be included in the fab command executed at the proxy server
env.proxy_hosts = []
env.proxy_roles = []

def is_running_on_proxy():
    """
    Returns True if this fabfile is being run on the proxy server.
    """
    return env.real_fabfile.find(env.proxy_home) < 0

def run_on_proxy(role=None, host=None):
    """
    Decorator that creates the actual decorator! This is necessary in order to
    be able to pass parameters to the actual decorator. Usage:

        @hosts(env.proxy_server)
        @run_on_proxy([host='somehost'|role='somerole'])
        def mytask():

    Each task must be surrounded by a @hosts decorator specifying the proxy server,
    so the task will be initially run at the proxy.

    Then the @run_on_proxy decorator can be used with or without specifying the actual
    servers where the task should be run. If no servers are specifyied, then the lists
    env.proxy_roles or env.proxy_hosts should be previously populated by some other task.
    """
    def actual_decorator(task):
        """
        Actual decorator that routes the task to be run on proxy.
        """
        def wrapper(*args, **kwargs):
            """
            Wrapper that checks if command is being run on proxy server.
            If it is, invokes fab again specifying some other server.
            If it is already being run on some other server, just execute the task.
            """
            if is_running_on_proxy():
                # There are several ways to specify in which other server this
                # task is to be run. Hosts/roles specified by the decorator itself
                # have higher priority.

                # If a role or host parameter was specified for the decorator, use them
                if role:
                    kwargs['role'] = role
                elif host:
                    kwargs['host'] = host
                # If some previous task populated the lists env.proxy_roles or proxy_hosts, use them
                elif env.proxy_roles:
                    kwargs['role'] = env.proxy_roles[0]
                elif env.proxy_hosts:
                    kwargs['host'] = env.proxy_hosts[0]

                with cd(env.proxy_home):
                    arguments = []
                    if args:
                        arguments.append(','.join(args))
                    if kwargs:
                        arguments.append(','.join(['%s=%s' % (k,v) for k,v in kwargs.items()]))
                    if args or kwargs:
                        command = 'fab %s:%s' % (task.__name__, ','.join(arguments))
                    else:
                        command = 'fab %s' % task.__name__
                    run(command)
            else:
                task(*args, **kwargs)

        return wrapper

    return actual_decorator
<commit_msg>Renaming decorators to start with "_" and avoid being listed in fab -l<commit_after># encoding: utf-8
# Fabmanager decorators

from fabric.api import *

# These variables must be defined at the actual fabfile.py
# Address of the proxy server intermediating the executation
#env.proxy_server = ''

# Location, at the proxy server, where fabfily.py will reside
#env.proxy_home = ''

# List of hosts and/or roles specified for this session - will
# be included in the fab command executed at the proxy server
#env.proxy_hosts = []
#env.proxy_roles = []

def _is_running_on_proxy():
    """
    Returns True if this fabfile is being run on the proxy server.
    """
    return env.real_fabfile.find(env.proxy_home) < 0

def _run_on_proxy(role=None, host=None):
    """
    Decorator that creates the actual decorator to route tasks through proxy.
    This is necessary in order to be able to pass parameters to the actual decorator.

    Usage:

        @hosts(env.proxy_server)
        @_run_on_proxy([host='somehost'|role='somerole'])
        def mytask():

    Each task must be surrounded by a @hosts decorator specifying the proxy server,
    so the task will be initially run at the proxy.

    Then the @_run_on_proxy decorator can be used with or without specifying the actual
    servers where the task should be run. If no servers are specifyied, then the lists
    env.proxy_roles or env.proxy_hosts should be previously populated by some other task.
    """
    def actual_decorator(task):
        """
        Actual decorator that routes the task to be run on proxy.
        """
        def wrapper(*args, **kwargs):
            """
            Wrapper that checks if command is being run on proxy server.
            If it is, invokes fab again specifying some other server.
            If it is already being run on some other server, just execute the task.
            """
            if _is_running_on_proxy():
                # There are several ways to specify in which other server this
                # task is to be run. Hosts/roles specified by the decorator itself
                # have higher priority.

                # If a role or host parameter was specified for the decorator, use them
                if role:
                    kwargs['role'] = role
                elif host:
                    kwargs['host'] = host
                # If some previous task populated the lists env.proxy_roles or proxy_hosts, use them
                elif env.proxy_roles:
                    kwargs['role'] = env.proxy_roles[0]
                elif env.proxy_hosts:
                    kwargs['host'] = env.proxy_hosts[0]

                with cd(env.proxy_home):
                    arguments = []
                    if args:
                        arguments.append(','.join(args))
                    if kwargs:
                        arguments.append(','.join(['%s=%s' % (k,v) for k,v in kwargs.items()]))
                    if args or kwargs:
                        run('fab %s:%s' % (task.__name__, ','.join(arguments)))
                    else:
                        run('fab %s' % task.__name__)
            else:
                task(*args, **kwargs)

        return wrapper

    return actual_decorator
<|endoftext|>


<commit_before>import re
from functools import singledispatch  # type: ignore

def snake_case(name: str) -> str:
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

@singledispatch
def decode(value):
    return value

@decode.register(bytes)
def decode_bytes(value):
    return value.decode()

@decode.register(list)
def decode_list(value):
    from amino import List
    return List.wrap(value).map(decode)

@decode.register(dict)
def decode_dict(value):
    from amino import Map
    return Map.wrap(value)\
        .keymap(decode)\
        .valmap(decode)

@decode.register(Exception)
def decode_exc(value):
    return decode_list(value.args).head | str(value)

def camelcaseify(name, sep='', splitter='_'):
    return sep.join([n.capitalize() for n in re.split(splitter, name)])

def safe_string(value):
    try:
        return str(value)
    except Exception:
        try:
            return repr(value)
        except Exception:
            return 'invalid'

__all__ = ('snake_case', 'decode', 'camelcaseify')
<commit_msg>`ToStr` convenience mixin that adds all values in `_arg_desc` to repr<commit_after>import re
import abc
from typing import Any
from functools import singledispatch

import amino

def snake_case(name: str) -> str:
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

@singledispatch
def decode(value: Any) -> Any:
    return value

@decode.register(bytes)
def decode_bytes(value: bytes) -> str:
    return value.decode()

@decode.register(list)
def decode_list(value: list) -> 'amino.List[str]':
    return amino.List.wrap(value).map(decode)

@decode.register(dict)
def decode_dict(value: dict) -> 'amino.Map[str, str]':
    return amino.Map.wrap(value).keymap(decode).valmap(decode)

@decode.register(Exception)
def decode_exc(value: Exception) -> str:
    return decode_list(value.args).head | str(value)

def camelcaseify(name: str, sep: str='', splitter: str='_') -> str:
    return sep.join([n.capitalize() for n in re.split(splitter, name)])

def safe_string(value: Any) -> str:
    try:
        return str(value)
    except Exception:
        try:
            return repr(value)
        except Exception:
            return 'invalid'

class ToStr(abc.ABC):

    @abc.abstractproperty
    def _arg_desc(self) -> 'amino.List[str]':
        ...

    def __str__(self) -> str:
        args = self._arg_desc.join_comma
        return f'{self.__class__.__name__}({args})'

    def __repr__(self) -> str:
        return str(self)

__all__ = ('snake_case', 'decode', 'camelcaseify')
<|endoftext|>


<commit_before>import json
import logging
import os
from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING, Callable, Dict

from core import utils
from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import NodeTypes
from core.errors import CoreCommandError
from core.nodes.base import CoreNode
from core.nodes.netclient import LinuxNetClient, get_net_client

if TYPE_CHECKING:
    from core.emulator.session import Session

class DockerClient:
    def __init__(self, name: str, image: str, run: Callable[..., str]) -> None:
        self.name = name
        self.image = image
        self.run = run
        self.pid = None

    def create_container(self) -> str:
        self.run(
            f"docker run -td --init --net=none --hostname {self.name} --name {self.name} "
            f"--sysctl net.ipv6.conf.all.disable_ipv6=0 {self.image} /bin/bash"
        )
        self.pid = self.get_pid()
        return self.pid

    def get_info(self) -> Dict:
        args = f"docker inspect {self.name}"
        output = self.run(args)
        data = json.loads(output)
        if not data:
            raise CoreCommandError(1, args, f"docker({self.name}) not present")
        return data[0]

    def is_alive(self) -> bool:
        try:
            data = self.get_info()
            return data["State"]["Running"]
        except CoreCommandError:
            return False

    def stop_container(self) -> None:
        self.run(f"docker rm -f {self.name}")

    def check_cmd(self, cmd: str, wait: bool = True, shell: bool = False) -> str:
        logging.info("docker cmd output: %s", cmd)
        return utils.cmd(f"docker exec {self.name} {cmd}", wait=wait, shell=shell)

    def create_ns_cmd(self, cmd: str) -> str:
        return f"nsenter -t {self.pid} -u -i -p -n {cmd}"

    def ns_cmd(self, cmd: str, wait: bool) -> str:
        args = f"nsenter -t {self.pid} -u -i -p -n {cmd}"
        return utils.cmd(args, wait=wait)

    def get_pid(self) -> str:
        args = f"docker inspect -f '{{{{.State.Pid}}}}' {self.name}"
        output = self.run(args)
        self.pid = output
        logging.debug("node(%s) pid: %s", self.name, self.pid)
        return output

    def copy_file(self, source: str, destination: str) -> str:
        args = f"docker cp {source} {self.name}:{destination}"
        return self.run(args)

class DockerNode(CoreNode):
    apitype = NodeTypes.DOCKER

    def __init__(
        self,
        session: "Session",
        _id: int = None,
        name: str = None,
        nodedir: str = None,
        bootsh: str = "boot.sh",
        start: bool = True,
        server: DistributedServer = None,
        image: str = None
    ) -> None:
        """
        Create a DockerNode instance.

        :param session: core session instance
        :param _id: object id
        :param name: object name
        :param nodedir: node directory
        :param bootsh: boot shell to use
        :param start: start flag
        :param server: remote server node
            will run on, default is None for localhost
        :param image: image to start container with
        """
        if image is None:
            image = "ubuntu"
        self.image = image
        super().__init__(session, _id, name, nodedir, bootsh, start, server)

    def create_node_net_client(self, use_ovs: bool) -> LinuxNetClient:
        """
        Create node network client for running network commands within the nodes
        container.

        :param use_ovs: True for OVS bridges, False for Linux bridges
        :return:node network client
        """
        return get_net_client(use_ovs, self.nsenter_cmd)

    def alive(self) -> bool:
        """
        Check if the node is alive.

        :return: True if node is alive, False otherwise
        """
        return self.client.is_alive()

    def startup(self) -> None:
        """
        Start a new namespace node by invoking the vnoded process that
        allocates a new namespace. Bring up the loopback device and set
        the hostname.

        :return: nothing
        """
        with self.lock:
            if self.up:
                raise ValueError("starting a node that is already up")
            self.makenodedir()
            self.client = DockerClient(self.name, self.image, self.host_cmd)
            self.pid = self.client.create_container()
            self.up = True

    def shutdown(self) -> None:
        """
        Shutdown logic.

        :return: nothing
        """
        # nothing to do if node is not up
        if not self.up:
            return

        with self.lock:
            self._netif.clear()
            self.client.stop_container()
            self.up = False

    def nsenter_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
        if self.server is None:
            args = self.client.create_ns_cmd(args)
            return utils.cmd(args, wait=wait, shell=shell)
        else:
            args = self.client.create_ns_cmd(args)
            return self.server.remote_cmd(args, wait=wait)

    def termcmdstring(self, sh: str = "/bin/sh") -> str:
        """
        Create a terminal command string.

        :param sh: shell to execute command in
        :return: str
        """
        return f"docker exec -it {self.name} bash"

    def privatedir(self, path: str) -> None:
        """
        Create a private directory.

        :param path: path to create
        :return: nothing
        """
        logging.debug("creating node dir: %s", path)
        args = f"mkdir -p {path}"
        self.cmd(args)

    def mount(self, source: str, target: str) -> None:
        """
        Create and mount a directory.

        :param source: source directory to mount
        :param target: target directory to create
        :return: nothing
        :raises CoreCommandError: when a non-zero exit status occurs
        """
        logging.debug("mounting source(%s) target(%s)", source, target)
        raise Exception("not supported")

    def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None:
        """
        Create a node file with a given mode.

        :param filename: name of file to create
        :param contents: contents of file
        :param mode: mode for file
        :return: nothing
        """
        logging.debug("nodefile filename(%s) mode(%s)", filename, mode)
        directory = os.path.dirname(filename)
        temp = NamedTemporaryFile(delete=False)
        temp.write(contents.encode("utf-8"))
        temp.close()

        if directory:
            self.cmd(f"mkdir -m {0o755:o} -p {directory}")
        if self.server is not None:
            self.server.remote_put(temp.name, temp.name)
        self.client.copy_file(temp.name, filename)
        self.cmd(f"chmod {mode:o} {filename}")
        if self.server is not None:
            self.host_cmd(f"rm -f {temp.name}")
        os.unlink(temp.name)
        logging.debug(
            "node(%s) added file: %s; mode: 0%o", self.name, filename, mode
        )

    def nodefilecopy(self, filename: str, srcfilename: str, mode: int = None) -> None:
        """
        Copy a file to a node, following symlinks and preserving metadata.
        Change file mode if specified.

        :param filename: file name to copy file to
        :param srcfilename: file to copy
        :param mode: mode to copy to
        :return: nothing
        """
        logging.info(
            "node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode
        )
        directory = os.path.dirname(filename)
        self.cmd(f"mkdir -p {directory}")

        if self.server is None:
            source = srcfilename
        else:
            temp = NamedTemporaryFile(delete=False)
            source = temp.name
            self.server.remote_put(source, temp.name)

        self.client.copy_file(source, filename)
        self.cmd(f"chmod {mode:o} {filename}")
<commit_msg>docker changes to avoid issues running commands without mount and running containers as prvileged to allow changing files in /sys<commit_after>import json
import logging
import os
from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING, Callable, Dict

from core import utils
from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import NodeTypes
from core.errors import CoreCommandError
from core.nodes.base import CoreNode
from core.nodes.netclient import LinuxNetClient, get_net_client

if TYPE_CHECKING:
    from core.emulator.session import Session

class DockerClient:
    def __init__(self, name: str, image: str, run: Callable[..., str]) -> None:
        self.name = name
        self.image = image
        self.run = run
        self.pid = None

    def create_container(self) -> str:
        self.run(
            f"docker run -td --init --net=none --hostname {self.name} "
            f"--name {self.name} --sysctl net.ipv6.conf.all.disable_ipv6=0 "
            f"--privileged {self.image} /bin/bash"
        )
        self.pid = self.get_pid()
        return self.pid

    def get_info(self) -> Dict:
        args = f"docker inspect {self.name}"
        output = self.run(args)
        data = json.loads(output)
        if not data:
            raise CoreCommandError(1, args, f"docker({self.name}) not present")
        return data[0]

    def is_alive(self) -> bool:
        try:
            data = self.get_info()
            return data["State"]["Running"]
        except CoreCommandError:
            return False

    def stop_container(self) -> None:
        self.run(f"docker rm -f {self.name}")

    def check_cmd(self, cmd: str, wait: bool = True, shell: bool = False) -> str:
        logging.info("docker cmd output: %s", cmd)
        return utils.cmd(f"docker exec {self.name} {cmd}", wait=wait, shell=shell)

    def create_ns_cmd(self, cmd: str) -> str:
        return f"nsenter -t {self.pid} -a {cmd}"

    def get_pid(self) -> str:
        args = f"docker inspect -f '{{{{.State.Pid}}}}' {self.name}"
        output = self.run(args)
        self.pid = output
        logging.debug("node(%s) pid: %s", self.name, self.pid)
        return output

    def copy_file(self, source: str, destination: str) -> str:
        args = f"docker cp {source} {self.name}:{destination}"
        return self.run(args)

class DockerNode(CoreNode):
    apitype = NodeTypes.DOCKER

    def __init__(
        self,
        session: "Session",
        _id: int = None,
        name: str = None,
        nodedir: str = None,
        bootsh: str = "boot.sh",
        start: bool = True,
        server: DistributedServer = None,
        image: str = None
    ) -> None:
        """
        Create a DockerNode instance.

        :param session: core session instance
        :param _id: object id
        :param name: object name
        :param nodedir: node directory
        :param bootsh: boot shell to use
        :param start: start flag
        :param server: remote server node
            will run on, default is None for localhost
        :param image: image to start container with
        """
        if image is None:
            image = "ubuntu"
        self.image = image
        super().__init__(session, _id, name, nodedir, bootsh, start, server)

    def create_node_net_client(self, use_ovs: bool) -> LinuxNetClient:
        """
        Create node network client for running network commands within the nodes
        container.

        :param use_ovs: True for OVS bridges, False for Linux bridges
        :return:node network client
        """
        return get_net_client(use_ovs, self.nsenter_cmd)

    def alive(self) -> bool:
        """
        Check if the node is alive.

        :return: True if node is alive, False otherwise
        """
        return self.client.is_alive()

    def startup(self) -> None:
        """
        Start a new namespace node by invoking the vnoded process that
        allocates a new namespace. Bring up the loopback device and set
        the hostname.

        :return: nothing
        """
        with self.lock:
            if self.up:
                raise ValueError("starting a node that is already up")
            self.makenodedir()
            self.client = DockerClient(self.name, self.image, self.host_cmd)
            self.pid = self.client.create_container()
            self.up = True

    def shutdown(self) -> None:
        """
        Shutdown logic.

        :return: nothing
        """
        # nothing to do if node is not up
        if not self.up:
            return

        with self.lock:
            self._netif.clear()
            self.client.stop_container()
            self.up = False

    def nsenter_cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
        if self.server is None:
            args = self.client.create_ns_cmd(args)
            return utils.cmd(args, wait=wait, shell=shell)
        else:
            args = self.client.create_ns_cmd(args)
            return self.server.remote_cmd(args, wait=wait)

    def termcmdstring(self, sh: str = "/bin/sh") -> str:
        """
        Create a terminal command string.

        :param sh: shell to execute command in
        :return: str
        """
        return f"docker exec -it {self.name} bash"

    def privatedir(self, path: str) -> None:
        """
        Create a private directory.

        :param path: path to create
        :return: nothing
        """
        logging.debug("creating node dir: %s", path)
        args = f"mkdir -p {path}"
        self.cmd(args)

    def mount(self, source: str, target: str) -> None:
        """
        Create and mount a directory.

        :param source: source directory to mount
        :param target: target directory to create
        :return: nothing
        :raises CoreCommandError: when a non-zero exit status occurs
        """
        logging.debug("mounting source(%s) target(%s)", source, target)
        raise Exception("not supported")

    def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None:
        """
        Create a node file with a given mode.

        :param filename: name of file to create
        :param contents: contents of file
        :param mode: mode for file
        :return: nothing
        """
        logging.debug("nodefile filename(%s) mode(%s)", filename, mode)
        directory = os.path.dirname(filename)
        temp = NamedTemporaryFile(delete=False)
        temp.write(contents.encode("utf-8"))
        temp.close()

        if directory:
            self.cmd(f"mkdir -m {0o755:o} -p {directory}")
        if self.server is not None:
            self.server.remote_put(temp.name, temp.name)
        self.client.copy_file(temp.name, filename)
        self.cmd(f"chmod {mode:o} {filename}")
        if self.server is not None:
            self.host_cmd(f"rm -f {temp.name}")
        os.unlink(temp.name)
        logging.debug(
            "node(%s) added file: %s; mode: 0%o", self.name, filename, mode
        )

    def nodefilecopy(self, filename: str, srcfilename: str, mode: int = None) -> None:
        """
        Copy a file to a node, following symlinks and preserving metadata.
        Change file mode if specified.

        :param filename: file name to copy file to
        :param srcfilename: file to copy
        :param mode: mode to copy to
        :return: nothing
        """
        logging.info(
            "node file copy file(%s) source(%s) mode(%s)", filename, srcfilename, mode
        )
        directory = os.path.dirname(filename)
        self.cmd(f"mkdir -p {directory}")

        if self.server is None:
            source = srcfilename
        else:
            temp = NamedTemporaryFile(delete=False)
            source = temp.name
            self.server.remote_put(source, temp.name)

        self.client.copy_file(source, filename)
        self.cmd(f"chmod {mode:o} {filename}")
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
rdfalchemy.py - a Simple API for RDF

Requires rdflib <http://www.rdflib.net/> version 2.3 ??.

"""

__license__ = """
Copyright (c) 2005-2007 Philip Cooper <Philip.Cooper@openvest.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
__version__ = "0.1dev"

from rdflib import ConjunctiveGraph
from rdflib import Literal, BNode, Namespace, URIRef
from itertools import chain
import re
import logging

console = logging.StreamHandler()
## console.setLevel(logging.DEBUG)    ## <- the debug level goes here
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
log=logging.getLogger('rdfAlchemy')
##log.setLevel(logging.DEBUG)
log.addHandler(console)

rdf  =Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
rdfs =Namespace("http://www.w3.org/2000/01/rdf-schema#")
owl  =Namespace("http://www.w3.org/2002/07/owl#")

re_ns_n = re.compile('(.*[/#])(.*)')

# Look into caching as in:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/276643
# Note: Non data descriptors (get only) lookup in obj.__dict__ first
#       Data descriptors (get and set) use the __get__ first

# helper function, might be somewhere in rdflib I need to look for it there
def getList(sub, pred=None, db=None):
    """Attempts to return a list from sub (subject that is)
    passed in if it is a Collection or a Container (Bag,Seq or Alt)"""
    if not db:
        if isinstance(sub,rdfObject):
            db=sub.db
        else:
            db=rdfObject.db
    if pred:
        if isinstance(sub, rdfObject):
            subUri=sub.resUri
        base = db.value(subUri,pred,any=True)
    else:
        # if there was no predicate assume a base node was passed in
        base=sub
    if type(base) != BNode:
        # Doesn't look like a list or a collection, just return multiple values (or an error?)
        val=[o for o in db.objects(subUri, pred)]
        return val
    members=[]
    first = db.value(base, rdf.first)
    # OK let's work at returning a list if there is an rdf.first
    if first:
        while first:
            members.append(first)
            base = db.value(base, rdf.rest)
            first = db.value(base, rdf.first)
        return members
    # OK let's work at returning a Collection (Seq,Bag or Alt) if was no rdf.first
    else:
        i=1
        first=db.value(base, rdf._1)
        if not first:
            raise AttributeError, "Not a list, or collection but another type of BNode"
        while first:
            members.append(first)
            i += 1
            first=db.value(base, rdf['_%d'%i])
        return members

class rdflibSingle(object):
    '''This is a Discriptor
    Takes a the URI of the predicate at initialization
    Expects to return a single item
    on Assignment will set that value to the
    ONLY triple with that subject,predicate pair'''
    def __init__(self, pred, cacheName=None):
        self.pred=pred
        self.name= cacheName or pred

    def __get__(self, obj, cls):
        if obj is None:
            return self
        if self.name in obj.__dict__:
            return obj.__dict__[self.name]
        log.debug("Geting with descriptor %s for %s"%(self.pred,obj.resUri))
        val=obj.__getitem__(self.pred)
        obj.__dict__[self.name]= val
        return val

    def __set__(self, obj, value):
        log.debug("SET with descriptor value %s of type %s"%(value,type(value)))
        #setattr(obj, self.name, value)  #this recurses indefinatly
        obj.__dict__[self.name]= value
        if isinstance(value,Literal):
            o = value
        elif isinstance(value,str):
            o = Literal(value,)
        else:
            o = Literal('What?')
        obj.db.set((obj.resUri,self.pred, o))
        #return None

    def __delete__(self, obj):
        # if this is a bnode like a list or a container a lot more should
        # be done ala getList above
        log.debug("DELETE with descriptor for %s on %s"%(self.pred, obj.resUri))
        return obj.db.remove((obj.resUri,self.pred, None))

class rdflibMultiple(object):
    '''This is a Discriptor
       Expects to return a list of values (could be a list of one)'''
    def __init__(self, pred, cacheName=None):
        self.pred=pred
        self.name= cacheName or pred

    def __get__(self, obj, cls):
        if obj is None:
            return self
        val=[o for o in obj.db.objects(obj.resUri, self.pred)]
	# check to see if this is a Container or Collection
        # if so, return collection as a list
	if len(val) == 1 \
           and (obj.db.value(o,rdf.first) or obj.db.value(o,rdf._1)):
                  val=getList(obj, self.pred)
        setattr(obj, self.name, val)
        try:
            log.info("Geting %s for %s"%(obj.db.qname(self.pred),obj.db.qname(obj.resUri)))
        except:
            log.info("Geting %s for %s"%(self.pred,obj.resUri))
        return val

class rdfObject(object):
    db=ConjunctiveGraph()
    rdf_type=''
    def __init__(self, resUri):
        if isinstance(resUri, rdfObject):
            self.resUri=resUri.resUri
            self.db=resUri.db
        elif isinstance(resUri, BNode):
            self.resUri=resUri
        else:
            self.resUri=URIRef(resUri)
        rdftype = list(self.db.objects(resUri, rdf.type))
        if len(rdftype)==1:
            self.namespace, trash = re_ns_n.match(rdftype[0]).groups()
            self.namespace=Namespace(self.namespace)
        elif isinstance(self.resUri,URIRef):
            ns_n =  re_ns_n.match(self.resUri)
            if ns_n:
                self.namespace, self.name = ns_n.groups()
                self.namespace=Namespace(self.namespace)

    def get_by(cls, **kwargs):
        if len(kwargs) != 1:
            raise ValueError("get_by did not want %i args"%(len(kwargs)))
        key,value = kwargs.items()[0]
        pred=cls.__dict__[key].pred
        uri=cls.db.value(None,pred,Literal(value))
        if uri:
            return cls(uri)
        else:
            raise LookupError("%s = %s not found"%(key,value))
    get_by=classmethod(get_by)

    def ClassInstances(cls):
        """return a generator for instances of this rdf:type
        you can look in MyClass.rdf_type to see the predicate being used"""
        for i in cls.db.subjects(rdf.type, cls.rdf_type):
            yield cls(i)
    ClassInstances=classmethod(ClassInstances)

    def GetRandom(cls):
        from random import randint
        xii=list(cls.ClassInstances())
        return xii[randint(0,len(xii)-1)]
    GetRandom=classmethod(GetRandom)

    def __repr__(self):
        return "<%s -> %s>"%(self.__class__, self.resUri)

    def __getitem__(self, pred):
        #log.debug("Geting with __getitem__ %s for %s"%(self.db.qname(pred),self.db.qname(self.resUri)))
        log.debug("Geting with __getitem__ %s for %s"%(pred,self.resUri))
        val=self.db.value(self.resUri,pred)
        if isinstance(val,Literal):
            val =  val.datatype and val.toPython() or unicode(val)
        elif isinstance(val, BNode) or isinstance(val,URIRef):
            val=rdfObject(val)
        return val

<commit_msg>modified rdfMultiple return to convert BNode and ResURI to rdfObject's<commit_after>#!/usr/bin/env python
"""
rdfalchemy.py - a Simple API for RDF

Requires rdflib <http://www.rdflib.net/> version 2.3 ??.

"""

__license__ = """
Copyright (c) 2005-2007 Philip Cooper <Philip.Cooper@openvest.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
__version__ = "0.1dev"

from rdflib import ConjunctiveGraph
from rdflib import Literal, BNode, Namespace, URIRef
from itertools import chain
import re
import logging

console = logging.StreamHandler()
## console.setLevel(logging.DEBUG)    ## <- the debug level goes here
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
log=logging.getLogger('rdfAlchemy')
##log.setLevel(logging.DEBUG)
log.addHandler(console)

rdf  =Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
rdfs =Namespace("http://www.w3.org/2000/01/rdf-schema#")
owl  =Namespace("http://www.w3.org/2002/07/owl#")

re_ns_n = re.compile('(.*[/#])(.*)')

# Look into caching as in:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/276643
# Note: Non data descriptors (get only) lookup in obj.__dict__ first
#       Data descriptors (get and set) use the __get__ first

# helper function, might be somewhere in rdflib I need to look for it there
def getList(sub, pred=None, db=None):
    """Attempts to return a list from sub (subject that is)
    passed in if it is a Collection or a Container (Bag,Seq or Alt)"""
    if not db:
        if isinstance(sub,rdfObject):
            db=sub.db
        else:
            db=rdfObject.db
    if pred:
        if isinstance(sub, rdfObject):
            subUri=sub.resUri
        base = db.value(subUri,pred,any=True)
    else:
        # if there was no predicate assume a base node was passed in
        base=sub
    if type(base) != BNode:
        # Doesn't look like a list or a collection, just return multiple values (or an error?)
        val=[o for o in db.objects(subUri, pred)]
        return val
    members=[]
    first = db.value(base, rdf.first)
    # OK let's work at returning a list if there is an rdf.first
    if first:
        while first:
            members.append(first)
            base = db.value(base, rdf.rest)
            first = db.value(base, rdf.first)
        return members
    # OK let's work at returning a Collection (Seq,Bag or Alt) if was no rdf.first
    else:
        i=1
        first=db.value(base, rdf._1)
        if not first:
            raise AttributeError, "Not a list, or collection but another type of BNode"
        while first:
            members.append(first)
            i += 1
            first=db.value(base, rdf['_%d'%i])
        return members

class rdflibSingle(object):
    '''This is a Discriptor
    Takes a the URI of the predicate at initialization
    Expects to return a single item
    on Assignment will set that value to the
    ONLY triple with that subject,predicate pair'''
    def __init__(self, pred, cacheName=None):
        self.pred=pred
        self.name= cacheName or pred

    def __get__(self, obj, cls):
        if obj is None:
            return self
        if self.name in obj.__dict__:
            return obj.__dict__[self.name]
        log.debug("Geting with descriptor %s for %s"%(self.pred,obj.resUri))
        val=obj.__getitem__(self.pred)
        obj.__dict__[self.name]= val
        return val

    def __set__(self, obj, value):
        log.debug("SET with descriptor value %s of type %s"%(value,type(value)))
        #setattr(obj, self.name, value)  #this recurses indefinatly
        obj.__dict__[self.name]= value
        if isinstance(value,Literal):
            o = value
        elif isinstance(value,str):
            o = Literal(value,)
        else:
            o = Literal('What?')
        obj.db.set((obj.resUri,self.pred, o))
        #return None

    def __delete__(self, obj):
        # if this is a bnode like a list or a container a lot more should
        # be done ala getList above
        log.debug("DELETE with descriptor for %s on %s"%(self.pred, obj.resUri))
        return obj.db.remove((obj.resUri,self.pred, None))

class rdflibMultiple(object):
    '''This is a Discriptor
       Expects to return a list of values (could be a list of one)'''
    def __init__(self, pred, cacheName=None):
        self.pred=pred
        self.name= cacheName or pred

    def __get__(self, obj, cls):
        if obj is None:
            return self
        val=[o for o in obj.db.objects(obj.resUri, self.pred)]
	# check to see if this is a Container or Collection
        # if so, return collection as a list
	if len(val) == 1 \
           and (obj.db.value(o,rdf.first) or obj.db.value(o,rdf._1)):
                  val=getList(obj, self.pred)
        val=[((isinstance(v,BNode) or isinstance(v,URIRef)) and rdfObject(v) or v) for v in val]
        setattr(obj, self.name, val)
        try:
            log.info("Geting %s for %s"%(obj.db.qname(self.pred),obj.db.qname(obj.resUri)))
        except:
            log.info("Geting %s for %s"%(self.pred,obj.resUri))
        return val

class rdfObject(object):
    db=ConjunctiveGraph()
    rdf_type=''
    def __init__(self, resUri):
        if isinstance(resUri, rdfObject):
            self.resUri=resUri.resUri
            self.db=resUri.db
        elif isinstance(resUri, BNode):
            self.resUri=resUri
        else:
            self.resUri=URIRef(resUri)
        rdftype = list(self.db.objects(resUri, rdf.type))
        if len(rdftype)==1:
            self.namespace, trash = re_ns_n.match(rdftype[0]).groups()
            self.namespace=Namespace(self.namespace)
        elif isinstance(self.resUri,URIRef):
            ns_n =  re_ns_n.match(self.resUri)
            if ns_n:
                self.namespace, self.name = ns_n.groups()
                self.namespace=Namespace(self.namespace)

    def get_by(cls, **kwargs):
        if len(kwargs) != 1:
            raise ValueError("get_by did not want %i args"%(len(kwargs)))
        key,value = kwargs.items()[0]
        pred=cls.__dict__[key].pred
        uri=cls.db.value(None,pred,Literal(value))
        if uri:
            return cls(uri)
        else:
            raise LookupError("%s = %s not found"%(key,value))
    get_by=classmethod(get_by)

    def ClassInstances(cls):
        """return a generator for instances of this rdf:type
        you can look in MyClass.rdf_type to see the predicate being used"""
        for i in cls.db.subjects(rdf.type, cls.rdf_type):
            yield cls(i)
    ClassInstances=classmethod(ClassInstances)

    def GetRandom(cls):
        from random import randint
        xii=list(cls.ClassInstances())
        return xii[randint(0,len(xii)-1)]
    GetRandom=classmethod(GetRandom)

    def __repr__(self):
        return "<%s -> %s>"%(self.__class__, self.resUri)

    def __getitem__(self, pred):
        #log.debug("Geting with __getitem__ %s for %s"%(self.db.qname(pred),self.db.qname(self.resUri)))
        log.debug("Geting with __getitem__ %s for %s"%(pred,self.resUri))
        val=self.db.value(self.resUri,pred)
        if isinstance(val,Literal):
            val =  val.datatype and val.toPython() or unicode(val)
        elif isinstance(val, BNode) or isinstance(val,URIRef):
            val=rdfObject(val)
        return val

<|endoftext|>


<commit_before># Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = [
    '__title__',
    '__summary__',
    '__url__',
    '__version__',
    '__author__',
    '__email__',
    '__license__',
]

__title__ = "okchef"
__summary__ = "python client library for Chef Server"
__keywords__ = ['chef', 'requests', 'client', 'api', 'requests-chef']
__url__ = "https://github.com/samstav/okchef"
__version__ = "1.1.2"
__author__ = "Sam Stavinoha"
__email__ = "samuel.stavinoha@rackspace.com"
__license__ = "Apache License, Version 2.0"
<commit_msg>bump version to 1.1.3<commit_after># Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__all__ = [
    '__title__',
    '__summary__',
    '__url__',
    '__version__',
    '__author__',
    '__email__',
    '__license__',
]

__title__ = "okchef"
__summary__ = "python client library for Chef Server"
__keywords__ = ['chef', 'requests', 'client', 'api', 'requests-chef']
__url__ = "https://github.com/samstav/okchef"
__version__ = "1.1.3"
__author__ = "Sam Stavinoha"
__email__ = "samuel.stavinoha@rackspace.com"
__license__ = "Apache License, Version 2.0"
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2014-2017 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.

import unittest
import mock
from openquake.calculators import base

class FakeParams(object):
    export_dir = '/tmp'
    hazard_calculation_id = None
    inputs = {'job_ini': 'fake_job.ini'}
    concurrent_tasks = 0

    def to_params(self):
        return {}

class ErrorCalculator(base.BaseCalculator):
    def pre_execute(self):
        pass

    def execute(self):
        1 / 0

    def post_execute(self):
        pass

class BaseCalculatorTestCase(unittest.TestCase):
    def test_critical(self):
        calc = ErrorCalculator(FakeParams())
        with mock.patch('logging.error') as error, mock.patch(
                'logging.critical') as critical:
            self.assertRaises(ZeroDivisionError, calc.run)
        self.assertEqual(error.call_count, 0)
        self.assertEqual(critical.call_count, 1)

class CheckHazardRiskConsistencyTestCase(unittest.TestCase):
    def test_ok(self):
        base.check_precalc_consistency('scenario_risk', 'scenario')

    def test_inconsistent_mode(self):
        with self.assertRaises(base.InvalidCalculationID) as ctx:
            base.check_precalc_consistency('classical_risk', 'scenario')
        msg = str(ctx.exception)
        self.assertEqual(
            msg, "In order to run a risk calculation of kind "
            "'classical_risk', you need to provide a "
            "calculation of kind ['classical'], "
            "but you provided a 'scenario' instead")
<commit_msg>Fixed BaseCalculatorTestCase<commit_after># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2014-2017 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.

import unittest
import mock
from openquake.baselib.general import writetmp
from openquake.calculators import base

class FakeParams(object):
    export_dir = '/tmp'
    hazard_calculation_id = None
    inputs = {'job_ini': writetmp('fake_job.ini')}
    concurrent_tasks = 0

    def to_params(self):
        return {}

class ErrorCalculator(base.BaseCalculator):
    def pre_execute(self):
        pass

    def execute(self):
        1 / 0

    def post_execute(self):
        pass

class BaseCalculatorTestCase(unittest.TestCase):
    def test_critical(self):
        calc = ErrorCalculator(FakeParams())
        with mock.patch('logging.error') as error, mock.patch(
                'logging.critical') as critical:
            self.assertRaises(ZeroDivisionError, calc.run)
        self.assertEqual(error.call_count, 0)
        self.assertEqual(critical.call_count, 1)

class CheckHazardRiskConsistencyTestCase(unittest.TestCase):
    def test_ok(self):
        base.check_precalc_consistency('scenario_risk', 'scenario')

    def test_inconsistent_mode(self):
        with self.assertRaises(base.InvalidCalculationID) as ctx:
            base.check_precalc_consistency('classical_risk', 'scenario')
        msg = str(ctx.exception)
        self.assertEqual(
            msg, "In order to run a risk calculation of kind "
            "'classical_risk', you need to provide a "
            "calculation of kind ['classical'], "
            "but you provided a 'scenario' instead")
<|endoftext|>