コード例 #1
0
ファイル: namespace_proxy.py プロジェクト: whitekid/quantum
def main():
    eventlet.monkey_patch()
    opts = [
        cfg.StrOpt('network_id'),
        cfg.StrOpt('router_id'),
        cfg.StrOpt('pid_file'),
        cfg.BoolOpt('daemonize', default=True),
        cfg.IntOpt('metadata_port',
                   default=9697,
                   help="TCP Port to listen for metadata server requests."),
    ]

    cfg.CONF.register_opts(opts)
    cfg.CONF(args=sys.argv, project='quantum')
    config.setup_logging(cfg.CONF)

    proxy = ProxyDaemon(cfg.CONF.pid_file,
                        cfg.CONF.metadata_port,
                        network_id=cfg.CONF.network_id,
                        router_id=cfg.CONF.router_id)

    if cfg.CONF.daemonize:
        proxy.start()
    else:
        proxy.run()
コード例 #2
0
class DhcpAgent(object):
    OPTS = [
        cfg.StrOpt('root_helper', default='sudo'),
        cfg.IntOpt('resync_interval', default=30),
        cfg.StrOpt('dhcp_driver',
                   default='quantum.agent.linux.dhcp.Dnsmasq',
                   help="The driver used to manage the DHCP server."),
        cfg.BoolOpt('use_namespaces', default=True,
                    help="Allow overlapping IP.")
    ]

    def __init__(self, conf):
        self.needs_resync = False
        self.conf = conf
        self.cache = NetworkCache()

        self.dhcp_driver_cls = importutils.import_class(conf.dhcp_driver)
        ctx = context.RequestContext('quantum', 'quantum', is_admin=True)
        self.plugin_rpc = DhcpPluginApi(topics.PLUGIN, ctx)

        self.device_manager = DeviceManager(self.conf, self.plugin_rpc)
        self.notifications = agent_rpc.NotificationDispatcher()
        self.lease_relay = DhcpLeaseRelay(self.update_lease)

    def run(self):
        """Activate the DHCP agent."""
        self.sync_state()
        self.periodic_resync()
        self.lease_relay.start()
        self.notifications.run_dispatch(self)

    def call_driver(self, action, network):
        """Invoke an action on a DHCP driver instance."""
        if self.conf.use_namespaces:
            namespace = NS_PREFIX + network.id
        else:
            namespace = None
        try:
            # the Driver expects something that is duck typed similar to
            # the base models.
            driver = self.dhcp_driver_cls(self.conf,
                                          network,
                                          self.conf.root_helper,
                                          self.device_manager,
                                          namespace)
            getattr(driver, action)()
            return True

        except Exception, e:
            self.needs_resync = True
            LOG.exception('Unable to %s dhcp.' % action)
コード例 #3
0
ファイル: netns_cleanup_util.py プロジェクト: jranjan/quantum
def setup_conf():
    """Setup the cfg for the clean up utility.

    Use separate setup_conf for the utility because there are many options
    from the main config that do not apply during clean-up.
    """

    opts = [
        cfg.StrOpt('root_helper', default='sudo'),
        cfg.StrOpt('dhcp_driver',
                   default='quantum.agent.linux.dhcp.Dnsmasq',
                   help="The driver used to manage the DHCP server."),
        cfg.StrOpt('state_path',
                   default='.',
                   help='Top-level directory for maintaining dhcp state'),
        cfg.BoolOpt('force',
                    default=False,
                    help='Delete the namespace by removing all devices.'),
    ]
    conf = cfg.CommonConfigOpts()
    conf.register_opts(opts)
    conf.register_opts(dhcp.OPTS)
    config.setup_logging(conf)
    return conf
コード例 #4
0
               default='',
               help='Username for qpid connection'),
    cfg.StrOpt('qpid_password',
               default='',
               help='Password for qpid connection'),
    cfg.StrOpt('qpid_sasl_mechanisms',
               default='',
               help='Space separated list of SASL mechanisms to use for auth'),
    cfg.IntOpt('qpid_heartbeat',
               default=60,
               help='Seconds between connection keepalive heartbeats'),
    cfg.StrOpt('qpid_protocol',
               default='tcp',
               help="Transport to use, either 'tcp' or 'ssl'"),
    cfg.BoolOpt('qpid_tcp_nodelay',
                default=True,
                help='Disable Nagle algorithm'),
]

cfg.CONF.register_opts(qpid_opts)


class ConsumerBase(object):
    """Consumer base class."""
    def __init__(self, session, callback, node_name, node_opts, link_name,
                 link_opts):
        """Declare a queue on an amqp session.

        'session' is the amqp session to use
        'callback' is the callback to call when messages are received
        'node_name' is the first part of the Qpid address string, before ';'
コード例 #5
0
ファイル: config.py プロジェクト: pulse-vadc/quantum

LOG = logging.getLogger(__name__)

core_opts = [
    cfg.StrOpt('bind_host', default='0.0.0.0'),
    cfg.IntOpt('bind_port', default=9696),
    cfg.StrOpt('api_paste_config', default="api-paste.ini"),
    cfg.StrOpt('api_extensions_path', default=""),
    cfg.StrOpt('policy_file', default="policy.json"),
    cfg.StrOpt('auth_strategy', default='keystone'),
    cfg.StrOpt('core_plugin',
               default='quantum.plugins.sample.SamplePlugin.FakePlugin'),
    cfg.StrOpt('base_mac', default="fa:16:3e:00:00:00"),
    cfg.IntOpt('mac_generation_retries', default=16),
    cfg.BoolOpt('allow_bulk', default=True),
    cfg.IntOpt('max_dns_nameservers', default=5),
    cfg.IntOpt('max_subnet_host_routes', default=20),
    cfg.StrOpt('state_path', default='.'),
    cfg.IntOpt('dhcp_lease_duration', default=120),
]

# Register the configuration options
cfg.CONF.register_opts(core_opts)


def parse(args):
    cfg.CONF(args=args, project='quantum',
             version='%%prog %s' % version_string())

    # Validate that the base_mac is of the correct format
コード例 #6
0
               help='data to append to log format when level is DEBUG'),
    cfg.StrOpt('logging_exception_prefix',
               default='%(asctime)s TRACE %(name)s %(instance)s',
               help='prefix each line of exception output with this format'),
    cfg.ListOpt('default_log_levels',
                default=[
                    'amqplib=WARN',
                    'sqlalchemy=WARN',
                    'boto=WARN',
                    'suds=INFO',
                    'keystone=INFO',
                    'eventlet.wsgi.server=WARN'
                ],
                help='list of logger=LEVEL pairs'),
    cfg.BoolOpt('publish_errors',
                default=False,
                help='publish error events'),

    # NOTE(mikal): there are two options here because sometimes we are handed
    # a full instance (and could include more information), and other times we
    # are just handed a UUID for the instance.
    cfg.StrOpt('instance_format',
               default='[instance: %(uuid)s] ',
               help='If an instance is passed with the log message, format '
                    'it like this'),
    cfg.StrOpt('instance_uuid_format',
               default='[instance: %(uuid)s] ',
               help='If an instance UUID is passed with the log message, '
                    'format it like this'),
]
コード例 #7
0
ファイル: lockutils.py プロジェクト: whitekid/quantum
import shutil
import tempfile
import time
import weakref

from eventlet import semaphore

from quantum.openstack.common import cfg
from quantum.openstack.common import fileutils
from quantum.openstack.common import log as logging

LOG = logging.getLogger(__name__)

util_opts = [
    cfg.BoolOpt('disable_process_locking',
                default=False,
                help='Whether to disable inter-process locks'),
    cfg.StrOpt('lock_path',
               default=os.path.abspath(
                   os.path.join(os.path.dirname(__file__), '../')),
               help='Directory to use for lock files')
]

CONF = cfg.CONF
CONF.register_opts(util_opts)


class _InterProcessLock(object):
    """Lock implementation which allows multiple locks, working around
    issues like bugs.debian.org/cgi-bin/bugreport.cgi?bug=632857 and does
    not require any cleanup. Since the lock is always held on a file
コード例 #8
0
class L3NATAgent(object):

    OPTS = [
        cfg.StrOpt('admin_user'),
        cfg.StrOpt('admin_password'),
        cfg.StrOpt('admin_tenant_name'),
        cfg.StrOpt('auth_url'),
        cfg.StrOpt('auth_strategy', default='keystone'),
        cfg.StrOpt('auth_region'),
        cfg.StrOpt('root_helper', default='sudo'),
        cfg.StrOpt('external_network_bridge', default='br-ex',
                   help="Name of bridge used for external network traffic."),
        cfg.StrOpt('interface_driver',
                   help="The driver used to manage the virtual interface."),
        cfg.IntOpt('polling_interval',
                   default=3,
                   help="The time in seconds between state poll requests."),
        cfg.StrOpt('metadata_ip', default='',
                   help="IP address used by Nova metadata server."),
        cfg.IntOpt('metadata_port',
                   default=8775,
                   help="TCP Port used by Nova metadata server."),
        cfg.IntOpt('send_arp_for_ha',
                   default=3,
                   help="Send this many gratuitous ARPs for HA setup, "
                        "set it below or equal to 0 to disable this feature."),
        cfg.BoolOpt('use_namespaces', default=True,
                    help="Allow overlapping IP."),
        cfg.StrOpt('router_id', default='',
                   help="If namespaces is disabled, the l3 agent can only"
                        " confgure a router that has the matching router ID."),
        cfg.BoolOpt('handle_internal_only_routers',
                    default=True,
                    help="Agent should implement routers with no gateway"),
        cfg.StrOpt('gateway_external_network_id', default='',
                   help="UUID of external network for routers implemented "
                        "by the agents."),
    ]

    def __init__(self, conf):
        self.conf = conf
        self.router_info = {}

        if not conf.interface_driver:
            LOG.error(_('You must specify an interface driver'))
            sys.exit(1)
        try:
            self.driver = importutils.import_object(conf.interface_driver,
                                                    conf)
        except:
            LOG.exception(_("Error importing interface driver '%s'"),
                          conf.interface_driver)
            sys.exit(1)

        self.polling_interval = conf.polling_interval

        self.qclient = client.Client(
            username=self.conf.admin_user,
            password=self.conf.admin_password,
            tenant_name=self.conf.admin_tenant_name,
            auth_url=self.conf.auth_url,
            auth_strategy=self.conf.auth_strategy,
            region_name=self.conf.auth_region
        )

        if self.conf.use_namespaces:
            self._destroy_all_router_namespaces()

    def _destroy_all_router_namespaces(self):
        """Destroy all router namespaces on the host to eliminate
        all stale linux devices, iptables rules, and namespaces.
        """
        root_ip = ip_lib.IPWrapper(self.conf.root_helper)
        for ns in root_ip.get_namespaces(self.conf.root_helper):
            if ns.startswith(NS_PREFIX):
                try:
                    self._destroy_router_namespace(ns)
                except:
                    LOG.exception(_("Couldn't delete namespace '%s'"), ns)

    def _destroy_router_namespace(self, namespace):
        ns_ip = ip_lib.IPWrapper(self.conf.root_helper,
                                 namespace=namespace)
        for d in ns_ip.get_devices(exclude_loopback=True):
            if d.name.startswith(INTERNAL_DEV_PREFIX):
                # device is on default bridge
                self.driver.unplug(d.name, namespace=namespace,
                                   prefix=INTERNAL_DEV_PREFIX)
            elif d.name.startswith(EXTERNAL_DEV_PREFIX):
                self.driver.unplug(d.name,
                                   bridge=self.conf.external_network_bridge,
                                   namespace=namespace,
                                   prefix=EXTERNAL_DEV_PREFIX)
        #(TODO) Address the failure for the deletion of the namespace

    def _create_router_namespace(self, ri):
            ip_wrapper_root = ip_lib.IPWrapper(self.conf.root_helper)
            ip_wrapper = ip_wrapper_root.ensure_namespace(ri.ns_name())
            ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])

    def daemon_loop(self):
        #TODO(danwent): this simple diff logic does not handle if
        # details of a router port (e.g., IP, mac) are changed behind
        # our back.  Will fix this properly with update notifications.

        while True:
            try:
                self.do_single_loop()
            except:
                LOG.exception(_("Error running l3_nat daemon_loop"))

            time.sleep(self.polling_interval)

    def _fetch_external_net_id(self):
        """Find UUID of single external network for this agent"""
        if self.conf.gateway_external_network_id:
            return self.conf.gateway_external_network_id

        params = {'router:external': True}
        ex_nets = self.qclient.list_networks(**params)['networks']
        if len(ex_nets) > 1:
            raise Exception(_("Must configure 'gateway_external_network_id' "
                              "if Quantum has more than one external "
                              "network."))
        if len(ex_nets) == 0:
            return None
        return ex_nets[0]['id']

    def do_single_loop(self):

        if (self.conf.external_network_bridge and
            not ip_lib.device_exists(self.conf.external_network_bridge)):
            LOG.error(_("External network bridge '%s' does not exist"),
                      self.conf.external_network_bridge)
            return

        prev_router_ids = set(self.router_info)
        cur_router_ids = set()

        target_ex_net_id = self._fetch_external_net_id()

        # identify and update new or modified routers
        for r in self.qclient.list_routers()['routers']:
            if not r['admin_state_up']:
                continue

            ex_net_id = (r['external_gateway_info'] and
                         r['external_gateway_info'].get('network_id'))
            if not ex_net_id and not self.conf.handle_internal_only_routers:
                continue

            if ex_net_id and ex_net_id != target_ex_net_id:
                continue

            # If namespaces are disabled, only process the router associated
            # with the configured agent id.
            if (self.conf.use_namespaces or
                r['id'] == self.conf.router_id):
                cur_router_ids.add(r['id'])
            else:
                continue
            if r['id'] not in self.router_info:
                self._router_added(r['id'])

            ri = self.router_info[r['id']]
            self.process_router(ri)

        # identify and remove routers that no longer exist
        for router_id in prev_router_ids - cur_router_ids:
            self._router_removed(router_id)
        prev_router_ids = cur_router_ids

    def _router_added(self, router_id):
        ri = RouterInfo(router_id, self.conf.root_helper,
                        self.conf.use_namespaces)
        self.router_info[router_id] = ri
        if self.conf.use_namespaces:
            self._create_router_namespace(ri)
        for c, r in self.metadata_filter_rules():
            ri.iptables_manager.ipv4['filter'].add_rule(c, r)
        for c, r in self.metadata_nat_rules():
            ri.iptables_manager.ipv4['nat'].add_rule(c, r)
        ri.iptables_manager.apply()

    def _router_removed(self, router_id):
        ri = self.router_info[router_id]
        for c, r in self.metadata_filter_rules():
            ri.iptables_manager.ipv4['filter'].remove_rule(c, r)
        for c, r in self.metadata_nat_rules():
            ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
        ri.iptables_manager.apply()
        del self.router_info[router_id]
        self._destroy_router_namespace(ri.ns_name())

    def _set_subnet_info(self, port):
        ips = port['fixed_ips']
        if not ips:
            raise Exception(_("Router port %s has no IP address") % port['id'])
        if len(ips) > 1:
            LOG.error(_("Ignoring multiple IPs on router port %s"), port['id'])
        port['subnet'] = self.qclient.show_subnet(
            ips[0]['subnet_id'])['subnet']
        prefixlen = netaddr.IPNetwork(port['subnet']['cidr']).prefixlen
        port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)

    def process_router(self, ri):

        ex_gw_port = self._get_ex_gw_port(ri)

        internal_ports = self.qclient.list_ports(
            device_id=ri.router_id,
            device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF)['ports']

        existing_port_ids = set([p['id'] for p in ri.internal_ports])
        current_port_ids = set([p['id'] for p in internal_ports
                                if p['admin_state_up']])
        new_ports = [p for p in internal_ports if
                     p['id'] in current_port_ids and
                     p['id'] not in existing_port_ids]
        old_ports = [p for p in ri.internal_ports if
                     p['id'] not in current_port_ids]

        for p in new_ports:
            self._set_subnet_info(p)
            ri.internal_ports.append(p)
            self.internal_network_added(ri, ex_gw_port,
                                        p['network_id'], p['id'],
                                        p['ip_cidr'], p['mac_address'])

        for p in old_ports:
            ri.internal_ports.remove(p)
            self.internal_network_removed(ri, ex_gw_port, p['id'],
                                          p['ip_cidr'])

        internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports]

        if ex_gw_port and not ri.ex_gw_port:
            self._set_subnet_info(ex_gw_port)
            self.external_gateway_added(ri, ex_gw_port, internal_cidrs)
        elif not ex_gw_port and ri.ex_gw_port:
            self.external_gateway_removed(ri, ri.ex_gw_port,
                                          internal_cidrs)

        if ri.ex_gw_port or ex_gw_port:
            self.process_router_floating_ips(ri, ex_gw_port)

        ri.ex_gw_port = ex_gw_port

    def process_router_floating_ips(self, ri, ex_gw_port):
        floating_ips = self.qclient.list_floatingips(
            router_id=ri.router_id)['floatingips']
        existing_floating_ip_ids = set([fip['id'] for fip in ri.floating_ips])
        cur_floating_ip_ids = set([fip['id'] for fip in floating_ips])

        id_to_fip_map = {}

        for fip in floating_ips:
            if fip['port_id']:
                if fip['id'] not in existing_floating_ip_ids:
                    ri.floating_ips.append(fip)
                    self.floating_ip_added(ri, ex_gw_port,
                                           fip['floating_ip_address'],
                                           fip['fixed_ip_address'])

                # store to see if floatingip was remapped
                id_to_fip_map[fip['id']] = fip

        floating_ip_ids_to_remove = (existing_floating_ip_ids -
                                     cur_floating_ip_ids)
        for fip in ri.floating_ips:
            if fip['id'] in floating_ip_ids_to_remove:
                ri.floating_ips.remove(fip)
                self.floating_ip_removed(ri, ri.ex_gw_port,
                                         fip['floating_ip_address'],
                                         fip['fixed_ip_address'])
            else:
                # handle remapping of a floating IP
                new_fip = id_to_fip_map[fip['id']]
                new_fixed_ip = new_fip['fixed_ip_address']
                existing_fixed_ip = fip['fixed_ip_address']
                if (new_fixed_ip and existing_fixed_ip and
                        new_fixed_ip != existing_fixed_ip):
                    floating_ip = fip['floating_ip_address']
                    self.floating_ip_removed(ri, ri.ex_gw_port,
                                             floating_ip, existing_fixed_ip)
                    self.floating_ip_added(ri, ri.ex_gw_port,
                                           floating_ip, new_fixed_ip)
                    ri.floating_ips.remove(fip)
                    ri.floating_ips.append(new_fip)

    def _get_ex_gw_port(self, ri):
        ports = self.qclient.list_ports(
            device_id=ri.router_id,
            device_owner=l3_db.DEVICE_OWNER_ROUTER_GW)['ports']
        if not ports:
            return None
        elif len(ports) == 1:
            return ports[0]
        else:
            LOG.error(_("Ignoring multiple gateway ports for router %s"),
                      ri.router_id)

    def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address):
        if self.conf.send_arp_for_ha > 0:
            arping_cmd = ['arping', '-A', '-U',
                          '-I', interface_name,
                          '-c', self.conf.send_arp_for_ha,
                          ip_address]
            try:
                if self.conf.use_namespaces:
                    ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
                                                  namespace=ri.ns_name())
                    ip_wrapper.netns.execute(arping_cmd, check_exit_code=True)
                else:
                    utils.execute(arping_cmd, check_exit_code=True,
                                  root_helper=self.conf.root_helper)
            except Exception as e:
                LOG.error(_("Failed sending gratuitous ARP: %s") % str(e))

    def get_internal_device_name(self, port_id):
        return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]

    def get_external_device_name(self, port_id):
        return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]

    def external_gateway_added(self, ri, ex_gw_port, internal_cidrs):

        interface_name = self.get_external_device_name(ex_gw_port['id'])
        ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
        if not ip_lib.device_exists(interface_name,
                                    root_helper=self.conf.root_helper,
                                    namespace=ri.ns_name()):
            self.driver.plug(ex_gw_port['network_id'],
                             ex_gw_port['id'], interface_name,
                             ex_gw_port['mac_address'],
                             bridge=self.conf.external_network_bridge,
                             namespace=ri.ns_name(),
                             prefix=EXTERNAL_DEV_PREFIX)
        self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']],
                            namespace=ri.ns_name())
        ip_address = ex_gw_port['ip_cidr'].split('/')[0]
        self._send_gratuitous_arp_packet(ri, interface_name, ip_address)

        gw_ip = ex_gw_port['subnet']['gateway_ip']
        if ex_gw_port['subnet']['gateway_ip']:
            cmd = ['route', 'add', 'default', 'gw', gw_ip]
            if self.conf.use_namespaces:
                ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
                                              namespace=ri.ns_name())
                ip_wrapper.netns.execute(cmd, check_exit_code=False)
            else:
                utils.execute(cmd, check_exit_code=False,
                              root_helper=self.conf.root_helper)

        for (c, r) in self.external_gateway_nat_rules(ex_gw_ip,
                                                      internal_cidrs,
                                                      interface_name):
            ri.iptables_manager.ipv4['nat'].add_rule(c, r)
        ri.iptables_manager.apply()

    def external_gateway_removed(self, ri, ex_gw_port, internal_cidrs):

        interface_name = self.get_external_device_name(ex_gw_port['id'])
        if ip_lib.device_exists(interface_name,
                                root_helper=self.conf.root_helper,
                                namespace=ri.ns_name()):
            self.driver.unplug(interface_name,
                               bridge=self.conf.external_network_bridge,
                               namespace=ri.ns_name(),
                               prefix=EXTERNAL_DEV_PREFIX)

        ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
        for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs,
                                                    interface_name):
            ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
        ri.iptables_manager.apply()

    def metadata_filter_rules(self):
        rules = []
        if self.conf.metadata_ip:
            rules.append(('INPUT', '-s 0.0.0.0/0 -d %s '
                          '-p tcp -m tcp --dport %s '
                          '-j ACCEPT' %
                         (self.conf.metadata_ip, self.conf.metadata_port)))
        return rules

    def metadata_nat_rules(self):
        rules = []
        if self.conf.metadata_ip:
            rules.append(('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 '
                         '-p tcp -m tcp --dport 80 -j DNAT '
                         '--to-destination %s:%s' %
                         (self.conf.metadata_ip, self.conf.metadata_port)))
        return rules

    def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs,
                                   interface_name):
        rules = [('POSTROUTING', '! -i %(interface_name)s '
                  '! -o %(interface_name)s -m conntrack ! '
                  '--ctstate DNAT -j ACCEPT' % locals())]
        for cidr in internal_cidrs:
            rules.extend(self.internal_network_nat_rules(ex_gw_ip, cidr))
        return rules

    def internal_network_added(self, ri, ex_gw_port, network_id, port_id,
                               internal_cidr, mac_address):
        interface_name = self.get_internal_device_name(port_id)
        if not ip_lib.device_exists(interface_name,
                                    root_helper=self.conf.root_helper,
                                    namespace=ri.ns_name()):
            self.driver.plug(network_id, port_id, interface_name, mac_address,
                             namespace=ri.ns_name(),
                             prefix=INTERNAL_DEV_PREFIX)

        self.driver.init_l3(interface_name, [internal_cidr],
                            namespace=ri.ns_name())
        ip_address = internal_cidr.split('/')[0]
        self._send_gratuitous_arp_packet(ri, interface_name, ip_address)

        if ex_gw_port:
            ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
            for c, r in self.internal_network_nat_rules(ex_gw_ip,
                                                        internal_cidr):
                ri.iptables_manager.ipv4['nat'].add_rule(c, r)
            ri.iptables_manager.apply()

    def internal_network_removed(self, ri, ex_gw_port, port_id, internal_cidr):
        interface_name = self.get_internal_device_name(port_id)
        if ip_lib.device_exists(interface_name,
                                root_helper=self.conf.root_helper,
                                namespace=ri.ns_name()):
            self.driver.unplug(interface_name, namespace=ri.ns_name(),
                               prefix=INTERNAL_DEV_PREFIX)

        if ex_gw_port:
            ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
            for c, r in self.internal_network_nat_rules(ex_gw_ip,
                                                        internal_cidr):
                ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
            ri.iptables_manager.apply()

    def internal_network_nat_rules(self, ex_gw_ip, internal_cidr):
        rules = [('snat', '-s %s -j SNAT --to-source %s' %
                 (internal_cidr, ex_gw_ip))]
        if self.conf.metadata_ip:
            rules.append(('POSTROUTING', '-s %s -d %s/32 -j ACCEPT' %
                          (internal_cidr, self.conf.metadata_ip)))
        return rules

    def floating_ip_added(self, ri, ex_gw_port, floating_ip, fixed_ip):
        ip_cidr = str(floating_ip) + '/32'
        interface_name = self.get_external_device_name(ex_gw_port['id'])
        device = ip_lib.IPDevice(interface_name, self.conf.root_helper,
                                 namespace=ri.ns_name())

        if not ip_cidr in [addr['cidr'] for addr in device.addr.list()]:
            net = netaddr.IPNetwork(ip_cidr)
            device.addr.add(net.version, ip_cidr, str(net.broadcast))
            self._send_gratuitous_arp_packet(ri, interface_name, floating_ip)

        for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
            ri.iptables_manager.ipv4['nat'].add_rule(chain, rule)
        ri.iptables_manager.apply()

    def floating_ip_removed(self, ri, ex_gw_port, floating_ip, fixed_ip):
        ip_cidr = str(floating_ip) + '/32'
        net = netaddr.IPNetwork(ip_cidr)
        interface_name = self.get_external_device_name(ex_gw_port['id'])

        device = ip_lib.IPDevice(interface_name, self.conf.root_helper,
                                 namespace=ri.ns_name())
        device.addr.delete(net.version, ip_cidr)

        for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
            ri.iptables_manager.ipv4['nat'].remove_rule(chain, rule)
        ri.iptables_manager.apply()

    def floating_forward_rules(self, floating_ip, fixed_ip):
        return [('PREROUTING', '-d %s -j DNAT --to %s' %
                 (floating_ip, fixed_ip)),
                ('OUTPUT', '-d %s -j DNAT --to %s' %
                 (floating_ip, fixed_ip)),
                ('float-snat', '-s %s -j SNAT --to %s' %
                 (fixed_ip, floating_ip))]
コード例 #9
0
ファイル: interface.py プロジェクト: whitekid/quantum
from quantum.agent.linux import ovs_lib
from quantum.agent.linux import utils
from quantum.common import exceptions
from quantum.extensions.flavor import (FLAVOR_NETWORK)
from quantum.openstack.common import cfg
from quantum.openstack.common import importutils
from quantum.openstack.common import log as logging

LOG = logging.getLogger(__name__)

OPTS = [
    cfg.StrOpt('ovs_integration_bridge',
               default='br-int',
               help='Name of Open vSwitch bridge to use'),
    cfg.BoolOpt('ovs_use_veth',
                default=False,
                help='Uses veth for an interface or not'),
    cfg.StrOpt('network_device_mtu', help='MTU setting for device.'),
    cfg.StrOpt('meta_flavor_driver_mappings',
               help='Mapping between flavor and LinuxInterfaceDriver')
]


class LinuxInterfaceDriver(object):
    __metaclass__ = abc.ABCMeta

    # from linux IF_NAMESIZE
    DEV_NAME_LEN = 14
    DEV_NAME_PREFIX = 'tap'

    def __init__(self, conf):
コード例 #10
0
qpid_opts = [
    cfg.StrOpt('qpid_hostname',
               default='localhost',
               help='Qpid broker hostname'),
    cfg.StrOpt('qpid_port', default='5672', help='Qpid broker port'),
    cfg.StrOpt('qpid_username',
               default='',
               help='Username for qpid connection'),
    cfg.StrOpt('qpid_password',
               default='',
               help='Password for qpid connection'),
    cfg.StrOpt('qpid_sasl_mechanisms',
               default='',
               help='Space separated list of SASL mechanisms to use for auth'),
    cfg.BoolOpt('qpid_reconnect', default=True,
                help='Automatically reconnect'),
    cfg.IntOpt('qpid_reconnect_timeout',
               default=0,
               help='Reconnection timeout in seconds'),
    cfg.IntOpt('qpid_reconnect_limit',
               default=0,
               help='Max reconnections before giving up'),
    cfg.IntOpt('qpid_reconnect_interval_min',
               default=0,
               help='Minimum seconds between reconnection attempts'),
    cfg.IntOpt('qpid_reconnect_interval_max',
               default=0,
               help='Maximum seconds between reconnection attempts'),
    cfg.IntOpt('qpid_reconnect_interval',
               default=0,
               help='Equivalent to setting max and min to the same value'),
コード例 #11
0
ファイル: log.py プロジェクト: whitekid/quantum
               help='data to append to log format when level is DEBUG'),
    cfg.StrOpt('logging_exception_prefix',
               default='%(asctime)s %(process)d TRACE %(name)s %(instance)s',
               help='prefix each line of exception output with this format'),
    cfg.ListOpt('default_log_levels',
                default=[
                    'amqplib=WARN',
                    'sqlalchemy=WARN',
                    'boto=WARN',
                    'suds=INFO',
                    'keystone=INFO',
                    'eventlet.wsgi.server=WARN'
                ],
                help='list of logger=LEVEL pairs'),
    cfg.BoolOpt('publish_errors',
                default=False,
                help='publish error events'),
    cfg.BoolOpt('fatal_deprecations',
                default=False,
                help='make deprecations fatal'),

    # NOTE(mikal): there are two options here because sometimes we are handed
    # a full instance (and could include more information), and other times we
    # are just handed a UUID for the instance.
    cfg.StrOpt('instance_format',
               default='[instance: %(uuid)s] ',
               help='If an instance is passed with the log message, format '
                    'it like this'),
    cfg.StrOpt('instance_uuid_format',
               default='[instance: %(uuid)s] ',
               help='If an instance UUID is passed with the log message, '
コード例 #12
0
ファイル: __init__.py プロジェクト: sunguoqiang/quantum
    cfg.IntOpt('rpc_cast_timeout',
               default=30,
               help='Seconds to wait before a cast expires (TTL). '
               'Only supported by impl_zmq.'),
    cfg.ListOpt('allowed_rpc_exception_modules',
                default=[
                    'quantum.openstack.common.exception',
                    'nova.exception',
                ],
                help='Modules of exceptions that are permitted to be recreated'
                'upon receiving exception data from an rpc call.'),
    cfg.StrOpt('control_exchange',
               default='nova',
               help='AMQP exchange to connect to if using RabbitMQ or Qpid'),
    cfg.BoolOpt('fake_rabbit',
                default=False,
                help='If passed, use a fake RabbitMQ provider'),
]

cfg.CONF.register_opts(rpc_opts)


def create_connection(new=True):
    """Create a connection to the message bus used for rpc.

    For some example usage of creating a connection and some consumers on that
    connection, see nova.service.

    :param new: Whether or not to create a new connection.  A new connection
                will be created by default.  If new is False, the
                implementation is free to return an existing connection from a
コード例 #13
0
ファイル: debug_agent.py プロジェクト: pulse-vadc/quantum
class QuantumDebugAgent():

    OPTS = [
        cfg.StrOpt('root_helper', default='sudo'),
        # Needed for drivers
        cfg.StrOpt('admin_user'),
        cfg.StrOpt('admin_password'),
        cfg.StrOpt('admin_tenant_name'),
        cfg.StrOpt('auth_url'),
        cfg.StrOpt('auth_strategy', default='keystone'),
        cfg.StrOpt('auth_region'),
        cfg.BoolOpt('use_namespaces', default=True),
        cfg.StrOpt('interface_driver',
                   help="The driver used to manage the virtual interface.")
    ]

    def __init__(self, conf, client, driver):
        self.conf = conf
        self.client = client
        self.driver = driver

    def _get_namespace(self, port):
        return "qprobe-%s" % port.id

    def create_probe(self, network_id):
        network = self._get_network(network_id)
        port = self._create_port(network)
        port.network = network
        interface_name = self.driver.get_device_name(port)
        namespace = None
        if self.conf.use_namespaces:
            namespace = self._get_namespace(port)

        if ip_lib.device_exists(interface_name, self.conf.root_helper,
                                namespace):
            LOG.debug(_('Reusing existing device: %s.') % interface_name)
        else:
            self.driver.plug(network.id,
                             port.id,
                             interface_name,
                             port.mac_address,
                             namespace=namespace)
        ip_cidrs = []
        for fixed_ip in port.fixed_ips:
            subnet = fixed_ip.subnet
            net = netaddr.IPNetwork(subnet.cidr)
            ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen)
            ip_cidrs.append(ip_cidr)
        self.driver.init_l3(interface_name, ip_cidrs, namespace=namespace)
        return port

    def _get_subnet(self, subnet_id):
        subnet_dict = self.client.show_subnet(subnet_id)['subnet']
        return DictModel(subnet_dict)

    def _get_network(self, network_id):
        network_dict = self.client.show_network(network_id)['network']
        network = DictModel(network_dict)
        obj_subnet = [self._get_subnet(s_id) for s_id in network.subnets]
        network.subnets = obj_subnet
        return network

    def clear_probe(self):
        ports = self.client.list_ports(device_id=socket.gethostname(),
                                       device_owner=DEVICE_OWNER_PROBE)
        info = ports['ports']
        for port in info:
            self.delete_probe(port['id'])

    def delete_probe(self, port_id):
        port = DictModel(self.client.show_port(port_id)['port'])
        ip = ip_lib.IPWrapper(self.conf.root_helper)
        namespace = self._get_namespace(port)
        if self.conf.use_namespaces and ip.netns.exists(namespace):
            self.driver.unplug(self.driver.get_device_name(port),
                               namespace=namespace)
            ip.netns.delete(namespace)
        else:
            self.driver.unplug(self.driver.get_device_name(port))
        self.client.delete_port(port.id)

    def list_probes(self):
        ports = self.client.list_ports(device_owner=DEVICE_OWNER_PROBE)
        info = ports['ports']
        for port in info:
            port['device_name'] = self.driver.get_device_name(DictModel(port))
        return info

    def exec_command(self, port_id, command=None):
        port = DictModel(self.client.show_port(port_id)['port'])
        ip = ip_lib.IPWrapper(self.conf.root_helper)
        namespace = self._get_namespace(port)
        if self.conf.use_namespaces:
            if not command:
                return "sudo ip netns exec %s" % self._get_namespace(port)
            namespace = ip.ensure_namespace(namespace)
            return namespace.netns.execute(shlex.split(command))
        else:
            return utils.execute(shlex.split(command))

    def ensure_probe(self, network_id):
        ports = self.client.list_ports(network_id=network_id,
                                       device_id=socket.gethostname(),
                                       device_owner=DEVICE_OWNER_PROBE)
        info = ports.get('ports', [])
        if info:
            return DictModel(info[0])
        else:
            return self.create_probe(network_id)

    def ping_all(self, network_id=None, timeout=1):
        if network_id:
            ports = self.client.list_ports(network_id=network_id)['ports']
        else:
            ports = self.client.list_ports()['ports']
        result = ""
        for port in ports:
            probe = self.ensure_probe(port['network_id'])
            if port['device_owner'] == DEVICE_OWNER_PROBE:
                continue
            for fixed_ip in port['fixed_ips']:
                address = fixed_ip['ip_address']
                subnet = self._get_subnet(fixed_ip['subnet_id'])
                if subnet.ip_version == 4:
                    ping_command = 'ping'
                else:
                    ping_command = 'ping6'
                result += self.exec_command(
                    probe.id,
                    '%s -c 1 -w %s %s' % (ping_command, timeout, address))
        return result

    def _create_port(self, network):
        body = dict(port=dict(
            admin_state_up=True,
            network_id=network.id,
            device_id='%s' % socket.gethostname(),
            device_owner=DEVICE_OWNER_PROBE,
            tenant_id=network.tenant_id,
            fixed_ips=[dict(subnet_id=s.id) for s in network.subnets]))
        port_dict = self.client.create_port(body)['port']
        port = DictModel(port_dict)
        port.network = network
        for fixed_ip in port.fixed_ips:
            fixed_ip.subnet = self._get_subnet(fixed_ip.subnet_id)
        return port
コード例 #14
0
]

ovs_opts = [
    cfg.StrOpt('integration_bridge', default='br-int'),
]

agent_opts = [
    cfg.IntOpt('polling_interval', default=2),
    cfg.StrOpt('root_helper', default='sudo'),
]

ofc_opts = [
    cfg.StrOpt('host', default='127.0.0.1'),
    cfg.StrOpt('port', default='8888'),
    cfg.StrOpt('driver', default='trema'),
    cfg.BoolOpt('enable_packet_filter', default=True),
    cfg.BoolOpt('use_ssl', default=False),
    cfg.StrOpt('key_file', default=None),
    cfg.StrOpt('cert_file', default=None),
]


cfg.CONF.register_opts(database_opts, "DATABASE")
cfg.CONF.register_opts(ovs_opts, "OVS")
cfg.CONF.register_opts(agent_opts, "AGENT")
cfg.CONF.register_opts(ofc_opts, "OFC")

# shortcuts
CONF = cfg.CONF
DATABASE = cfg.CONF.DATABASE
OVS = cfg.CONF.OVS
コード例 #15
0
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from quantum.openstack.common import cfg


database_opts = [
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('reconnect_interval', default=2),
]

ovs_opts = [
    cfg.BoolOpt('enable_tunneling', default=False),
    cfg.StrOpt('integration_bridge', default='br-int'),
    cfg.StrOpt('tunnel_bridge', default='br-tun'),
    cfg.StrOpt('local_ip', default='10.0.0.3'),
    cfg.IntOpt('vlan_min', default=1),
    cfg.IntOpt('vlan_max', default=4094),
]

agent_opts = [
    cfg.BoolOpt('target_v2_api', default=True),
    cfg.IntOpt('polling_interval', default=2),
    cfg.StrOpt('root_helper', default='sudo'),
    cfg.StrOpt('log_file', default=None),
]

コード例 #16
0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from quantum.openstack.common import cfg

database_opts = [
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('reconnect_interval', default=2),
]

ovs_opts = [
    cfg.BoolOpt('enable_tunneling', default=False),
    cfg.StrOpt('integration_bridge', default='br-int'),
    cfg.StrOpt('tunnel_bridge', default='br-tun'),
    cfg.StrOpt('local_ip', default='10.0.0.3'),
    cfg.IntOpt('vlan_min', default=1),
    cfg.IntOpt('vlan_max', default=4094),
]

agent_opts = [
    cfg.IntOpt('polling_interval', default=2),
    cfg.StrOpt('root_helper', default='sudo'),
]


def parse(config_file):
    conf = cfg.ConfigOpts(default_config_files=[config_file])
コード例 #17
0
from quantum.openstack.common import cfg

DEFAULT_BRIDGE_MAPPINGS = []
DEFAULT_VLAN_RANGES = []
DEFAULT_TUNNEL_RANGES = []

database_opts = [
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('sql_max_retries', default=-1),
    cfg.IntOpt('reconnect_interval', default=2),
]

ovs_opts = [
    cfg.StrOpt('integration_bridge', default='br-int'),
    cfg.BoolOpt('enable_tunneling', default=False),
    cfg.StrOpt('tunnel_bridge', default='br-tun'),
    cfg.StrOpt('local_ip', default=''),
    cfg.ListOpt('bridge_mappings',
                default=DEFAULT_BRIDGE_MAPPINGS,
                help="List of <physical_network>:<bridge>"),
    cfg.StrOpt('tenant_network_type',
               default='local',
               help="Network type for tenant networks "
               "(local, vlan, gre, or none)"),
    cfg.ListOpt('network_vlan_ranges',
                default=DEFAULT_VLAN_RANGES,
                help="List of <physical_network>:<vlan_min>:<vlan_max> "
                "or <physical_network>"),
    cfg.ListOpt('tunnel_id_ranges',
                default=DEFAULT_TUNNEL_RANGES,
コード例 #18
0
            default='',
            help='SSL version to use (valid only if SSL enabled)'),
 cfg.StrOpt('kombu_ssl_keyfile',
            default='',
            help='SSL key file (valid only if SSL enabled)'),
 cfg.StrOpt('kombu_ssl_certfile',
            default='',
            help='SSL cert file (valid only if SSL enabled)'),
 cfg.StrOpt('kombu_ssl_ca_certs',
            default='',
            help=('SSL certification authority file '
                  '(valid only if SSL enabled)')),
 cfg.StrOpt('rabbit_host', default='localhost', help='the RabbitMQ host'),
 cfg.IntOpt('rabbit_port', default=5672, help='the RabbitMQ port'),
 cfg.BoolOpt('rabbit_use_ssl',
             default=False,
             help='connect over SSL for RabbitMQ'),
 cfg.StrOpt('rabbit_userid', default='guest', help='the RabbitMQ userid'),
 cfg.StrOpt('rabbit_password',
            default='guest',
            help='the RabbitMQ password'),
 cfg.StrOpt('rabbit_virtual_host',
            default='/',
            help='the RabbitMQ virtual host'),
 cfg.IntOpt('rabbit_retry_interval',
            default=1,
            help='how frequently to retry connecting with RabbitMQ'),
 cfg.IntOpt('rabbit_retry_backoff',
            default=2,
            help='how long to backoff for between retries when connecting '
            'to RabbitMQ'),
コード例 #19
0
ファイル: config.py プロジェクト: redondos/quantum
LOG = logging.getLogger(__name__)

core_opts = [
    cfg.StrOpt('bind_host', default='0.0.0.0'),
    cfg.IntOpt('bind_port', default=9696),
    cfg.StrOpt('api_paste_config', default="api-paste.ini"),
    cfg.StrOpt('api_extensions_path', default=""),
    cfg.StrOpt('policy_file', default="policy.json"),
    cfg.StrOpt('auth_strategy', default='keystone'),
    cfg.StrOpt('core_plugin',
               default='quantum.plugins.sample.SamplePlugin.FakePlugin'),
    cfg.ListOpt('service_plugins', default=[]),
    cfg.StrOpt('base_mac', default="fa:16:3e:00:00:00"),
    cfg.IntOpt('mac_generation_retries', default=16),
    cfg.BoolOpt('allow_bulk', default=True),
    cfg.IntOpt('max_dns_nameservers', default=5),
    cfg.IntOpt('max_subnet_host_routes', default=20),
    cfg.StrOpt('state_path', default='.'),
    cfg.IntOpt('dhcp_lease_duration', default=120),
    cfg.BoolOpt('allow_overlapping_ips', default=False),
    cfg.StrOpt('control_exchange',
               default='quantum',
               help='AMQP exchange to connect to if using RabbitMQ or Qpid')
]

# Register the configuration options
cfg.CONF.register_opts(core_opts)


def parse(args):
コード例 #20
0
class L3NATAgent(manager.Manager):

    OPTS = [
        cfg.StrOpt('root_helper', default='sudo'),
        cfg.StrOpt('external_network_bridge',
                   default='br-ex',
                   help="Name of bridge used for external network traffic."),
        cfg.StrOpt('interface_driver',
                   help="The driver used to manage the virtual interface."),
        cfg.IntOpt('metadata_port',
                   default=9697,
                   help="TCP Port used by Quantum metadata namespace proxy."),
        cfg.IntOpt('send_arp_for_ha',
                   default=3,
                   help="Send this many gratuitous ARPs for HA setup, "
                   "set it below or equal to 0 to disable this feature."),
        cfg.BoolOpt('use_namespaces',
                    default=True,
                    help="Allow overlapping IP."),
        cfg.StrOpt('router_id',
                   default='',
                   help="If namespaces is disabled, the l3 agent can only"
                   " confgure a router that has the matching router ID."),
        cfg.BoolOpt('handle_internal_only_routers',
                    default=True,
                    help="Agent should implement routers with no gateway"),
        cfg.StrOpt('gateway_external_network_id',
                   default='',
                   help="UUID of external network for routers implemented "
                   "by the agents."),
        cfg.StrOpt('l3_agent_manager',
                   default='quantum.agent.l3_agent.L3NATAgent'),
    ]

    def __init__(self, host, conf=None):
        if conf:
            self.conf = conf
        else:
            self.conf = cfg.CONF
        self.router_info = {}

        if not self.conf.interface_driver:
            LOG.error(_('An interface driver must be specified'))
            sys.exit(1)
        try:
            self.driver = importutils.import_object(self.conf.interface_driver,
                                                    self.conf)
        except:
            LOG.exception(
                _("Error importing interface driver '%s'" %
                  self.conf.interface_driver))
            sys.exit(1)
        self.plugin_rpc = L3PluginApi(topics.PLUGIN, host)
        self.fullsync = True
        self.sync_sem = semaphore.Semaphore(1)
        if self.conf.use_namespaces:
            self._destroy_all_router_namespaces()
        super(L3NATAgent, self).__init__(host=self.conf.host)

    def _destroy_all_router_namespaces(self):
        """Destroy all router namespaces on the host to eliminate
        all stale linux devices, iptables rules, and namespaces.
        """
        root_ip = ip_lib.IPWrapper(self.conf.root_helper)
        for ns in root_ip.get_namespaces(self.conf.root_helper):
            if ns.startswith(NS_PREFIX):
                try:
                    self._destroy_router_namespace(ns)
                except:
                    LOG.exception(_("Failed deleting namespace '%s'") % ns)

    def _destroy_router_namespace(self, namespace):
        ns_ip = ip_lib.IPWrapper(self.conf.root_helper, namespace=namespace)
        for d in ns_ip.get_devices(exclude_loopback=True):
            if d.name.startswith(INTERNAL_DEV_PREFIX):
                # device is on default bridge
                self.driver.unplug(d.name,
                                   namespace=namespace,
                                   prefix=INTERNAL_DEV_PREFIX)
            elif d.name.startswith(EXTERNAL_DEV_PREFIX):
                self.driver.unplug(d.name,
                                   bridge=self.conf.external_network_bridge,
                                   namespace=namespace,
                                   prefix=EXTERNAL_DEV_PREFIX)
        #(TODO) Address the failure for the deletion of the namespace

    def _create_router_namespace(self, ri):
        ip_wrapper_root = ip_lib.IPWrapper(self.conf.root_helper)
        ip_wrapper = ip_wrapper_root.ensure_namespace(ri.ns_name())
        ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])

    def _fetch_external_net_id(self):
        """Find UUID of single external network for this agent"""
        if self.conf.gateway_external_network_id:
            return self.conf.gateway_external_network_id
        try:
            return self.plugin_rpc.get_external_network_id(
                context.get_admin_context())
        except rpc_common.RemoteError as e:
            if e.exc_type == 'TooManyExternalNetworks':
                msg = _("The 'gateway_external_network_id' must be configured"
                        " if Quantum has more than one external network.")
                raise Exception(msg)
            else:
                raise

    def _router_added(self, router_id, router=None):
        ri = RouterInfo(router_id, self.conf.root_helper,
                        self.conf.use_namespaces, router)
        self.router_info[router_id] = ri
        if self.conf.use_namespaces:
            self._create_router_namespace(ri)
        for c, r in self.metadata_filter_rules():
            ri.iptables_manager.ipv4['filter'].add_rule(c, r)
        for c, r in self.metadata_nat_rules():
            ri.iptables_manager.ipv4['nat'].add_rule(c, r)
        ri.iptables_manager.apply()
        self._spawn_metadata_agent(ri)

    def _router_removed(self, router_id):
        ri = self.router_info[router_id]
        for c, r in self.metadata_filter_rules():
            ri.iptables_manager.ipv4['filter'].remove_rule(c, r)
        for c, r in self.metadata_nat_rules():
            ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
        ri.iptables_manager.apply()
        self._destroy_metadata_agent(ri)
        del self.router_info[router_id]
        self._destroy_router_namespace(ri.ns_name())

    def _spawn_metadata_agent(self, router_info):
        def callback(pid_file):
            return [
                'quantum-ns-metadata-proxy',
                '--pid_file=%s' % pid_file,
                '--router_id=%s' % router_info.router_id,
                '--state_path=%s' % self.conf.state_path
            ]

        pm = external_process.ProcessManager(self.conf, router_info.router_id,
                                             self.conf.root_helper,
                                             router_info.ns_name())
        pm.enable(callback)

    def _destroy_metadata_agent(self, router_info):
        pm = external_process.ProcessManager(self.conf, router_info.router_id,
                                             self.conf.root_helper,
                                             router_info.ns_name())
        pm.disable()

    def _set_subnet_info(self, port):
        ips = port['fixed_ips']
        if not ips:
            raise Exception(_("Router port %s has no IP address") % port['id'])
        if len(ips) > 1:
            LOG.error(
                _("Ignoring multiple IPs on router port %s") % port['id'])
        prefixlen = netaddr.IPNetwork(port['subnet']['cidr']).prefixlen
        port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)

    def process_router(self, ri):

        ex_gw_port = self._get_ex_gw_port(ri)
        internal_ports = ri.router.get(l3_constants.INTERFACE_KEY, [])
        existing_port_ids = set([p['id'] for p in ri.internal_ports])
        current_port_ids = set(
            [p['id'] for p in internal_ports if p['admin_state_up']])
        new_ports = [
            p for p in internal_ports
            if p['id'] in current_port_ids and p['id'] not in existing_port_ids
        ]
        old_ports = [
            p for p in ri.internal_ports if p['id'] not in current_port_ids
        ]

        for p in new_ports:
            self._set_subnet_info(p)
            ri.internal_ports.append(p)
            self.internal_network_added(ri, ex_gw_port, p['network_id'],
                                        p['id'], p['ip_cidr'],
                                        p['mac_address'])

        for p in old_ports:
            ri.internal_ports.remove(p)
            self.internal_network_removed(ri, ex_gw_port, p['id'],
                                          p['ip_cidr'])

        internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports]

        if ex_gw_port and not ri.ex_gw_port:
            self._set_subnet_info(ex_gw_port)
            self.external_gateway_added(ri, ex_gw_port, internal_cidrs)
        elif not ex_gw_port and ri.ex_gw_port:
            self.external_gateway_removed(ri, ri.ex_gw_port, internal_cidrs)

        if ri.ex_gw_port or ex_gw_port:
            self.process_router_floating_ips(ri, ex_gw_port)

        ri.ex_gw_port = ex_gw_port

    def process_router_floating_ips(self, ri, ex_gw_port):
        floating_ips = ri.router.get(l3_constants.FLOATINGIP_KEY, [])
        existing_floating_ip_ids = set([fip['id'] for fip in ri.floating_ips])
        cur_floating_ip_ids = set([fip['id'] for fip in floating_ips])

        id_to_fip_map = {}

        for fip in floating_ips:
            if fip['port_id']:
                if fip['id'] not in existing_floating_ip_ids:
                    ri.floating_ips.append(fip)
                    self.floating_ip_added(ri, ex_gw_port,
                                           fip['floating_ip_address'],
                                           fip['fixed_ip_address'])

                # store to see if floatingip was remapped
                id_to_fip_map[fip['id']] = fip

        floating_ip_ids_to_remove = (existing_floating_ip_ids -
                                     cur_floating_ip_ids)
        for fip in ri.floating_ips:
            if fip['id'] in floating_ip_ids_to_remove:
                ri.floating_ips.remove(fip)
                self.floating_ip_removed(ri, ri.ex_gw_port,
                                         fip['floating_ip_address'],
                                         fip['fixed_ip_address'])
            else:
                # handle remapping of a floating IP
                new_fip = id_to_fip_map[fip['id']]
                new_fixed_ip = new_fip['fixed_ip_address']
                existing_fixed_ip = fip['fixed_ip_address']
                if (new_fixed_ip and existing_fixed_ip
                        and new_fixed_ip != existing_fixed_ip):
                    floating_ip = fip['floating_ip_address']
                    self.floating_ip_removed(ri, ri.ex_gw_port, floating_ip,
                                             existing_fixed_ip)
                    self.floating_ip_added(ri, ri.ex_gw_port, floating_ip,
                                           new_fixed_ip)
                    ri.floating_ips.remove(fip)
                    ri.floating_ips.append(new_fip)

    def _get_ex_gw_port(self, ri):
        return ri.router.get('gw_port')

    def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address):
        if self.conf.send_arp_for_ha > 0:
            arping_cmd = [
                'arping', '-A', '-U', '-I', interface_name, '-c',
                self.conf.send_arp_for_ha, ip_address
            ]
            try:
                if self.conf.use_namespaces:
                    ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
                                                  namespace=ri.ns_name())
                    ip_wrapper.netns.execute(arping_cmd, check_exit_code=True)
                else:
                    utils.execute(arping_cmd,
                                  check_exit_code=True,
                                  root_helper=self.conf.root_helper)
            except Exception as e:
                LOG.error(_("Failed sending gratuitous ARP: %s") % str(e))

    def get_internal_device_name(self, port_id):
        return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]

    def get_external_device_name(self, port_id):
        return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]

    def external_gateway_added(self, ri, ex_gw_port, internal_cidrs):

        interface_name = self.get_external_device_name(ex_gw_port['id'])
        ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
        if not ip_lib.device_exists(interface_name,
                                    root_helper=self.conf.root_helper,
                                    namespace=ri.ns_name()):
            self.driver.plug(ex_gw_port['network_id'],
                             ex_gw_port['id'],
                             interface_name,
                             ex_gw_port['mac_address'],
                             bridge=self.conf.external_network_bridge,
                             namespace=ri.ns_name(),
                             prefix=EXTERNAL_DEV_PREFIX)
        self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']],
                            namespace=ri.ns_name())
        ip_address = ex_gw_port['ip_cidr'].split('/')[0]
        self._send_gratuitous_arp_packet(ri, interface_name, ip_address)

        gw_ip = ex_gw_port['subnet']['gateway_ip']
        if ex_gw_port['subnet']['gateway_ip']:
            cmd = ['route', 'add', 'default', 'gw', gw_ip]
            if self.conf.use_namespaces:
                ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
                                              namespace=ri.ns_name())
                ip_wrapper.netns.execute(cmd, check_exit_code=False)
            else:
                utils.execute(cmd,
                              check_exit_code=False,
                              root_helper=self.conf.root_helper)

        for (c, r) in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs,
                                                      interface_name):
            ri.iptables_manager.ipv4['nat'].add_rule(c, r)
        ri.iptables_manager.apply()

    def external_gateway_removed(self, ri, ex_gw_port, internal_cidrs):

        interface_name = self.get_external_device_name(ex_gw_port['id'])
        if ip_lib.device_exists(interface_name,
                                root_helper=self.conf.root_helper,
                                namespace=ri.ns_name()):
            self.driver.unplug(interface_name,
                               bridge=self.conf.external_network_bridge,
                               namespace=ri.ns_name(),
                               prefix=EXTERNAL_DEV_PREFIX)

        ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
        for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs,
                                                    interface_name):
            ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
        ri.iptables_manager.apply()

    def metadata_filter_rules(self):
        rules = []
        rules.append(('INPUT', '-s 0.0.0.0/0 -d 127.0.0.1 '
                      '-p tcp -m tcp --dport %s '
                      '-j ACCEPT' % self.conf.metadata_port))
        return rules

    def metadata_nat_rules(self):
        rules = []
        rules.append(('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 '
                      '-p tcp -m tcp --dport 80 -j REDIRECT '
                      '--to-port %s' % self.conf.metadata_port))
        return rules

    def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs,
                                   interface_name):
        rules = [('POSTROUTING', '! -i %(interface_name)s '
                  '! -o %(interface_name)s -m conntrack ! '
                  '--ctstate DNAT -j ACCEPT' % locals())]
        for cidr in internal_cidrs:
            rules.extend(self.internal_network_nat_rules(ex_gw_ip, cidr))
        return rules

    def internal_network_added(self, ri, ex_gw_port, network_id, port_id,
                               internal_cidr, mac_address):
        interface_name = self.get_internal_device_name(port_id)
        if not ip_lib.device_exists(interface_name,
                                    root_helper=self.conf.root_helper,
                                    namespace=ri.ns_name()):
            self.driver.plug(network_id,
                             port_id,
                             interface_name,
                             mac_address,
                             namespace=ri.ns_name(),
                             prefix=INTERNAL_DEV_PREFIX)

        self.driver.init_l3(interface_name, [internal_cidr],
                            namespace=ri.ns_name())
        ip_address = internal_cidr.split('/')[0]
        self._send_gratuitous_arp_packet(ri, interface_name, ip_address)

        if ex_gw_port:
            ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
            for c, r in self.internal_network_nat_rules(
                    ex_gw_ip, internal_cidr):
                ri.iptables_manager.ipv4['nat'].add_rule(c, r)
            ri.iptables_manager.apply()

    def internal_network_removed(self, ri, ex_gw_port, port_id, internal_cidr):
        interface_name = self.get_internal_device_name(port_id)
        if ip_lib.device_exists(interface_name,
                                root_helper=self.conf.root_helper,
                                namespace=ri.ns_name()):
            self.driver.unplug(interface_name,
                               namespace=ri.ns_name(),
                               prefix=INTERNAL_DEV_PREFIX)

        if ex_gw_port:
            ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
            for c, r in self.internal_network_nat_rules(
                    ex_gw_ip, internal_cidr):
                ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
            ri.iptables_manager.apply()

    def internal_network_nat_rules(self, ex_gw_ip, internal_cidr):
        rules = [('snat',
                  '-s %s -j SNAT --to-source %s' % (internal_cidr, ex_gw_ip))]
        return rules

    def floating_ip_added(self, ri, ex_gw_port, floating_ip, fixed_ip):
        ip_cidr = str(floating_ip) + '/32'
        interface_name = self.get_external_device_name(ex_gw_port['id'])
        device = ip_lib.IPDevice(interface_name,
                                 self.conf.root_helper,
                                 namespace=ri.ns_name())

        if not ip_cidr in [addr['cidr'] for addr in device.addr.list()]:
            net = netaddr.IPNetwork(ip_cidr)
            device.addr.add(net.version, ip_cidr, str(net.broadcast))
            self._send_gratuitous_arp_packet(ri, interface_name, floating_ip)

        for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
            ri.iptables_manager.ipv4['nat'].add_rule(chain, rule)
        ri.iptables_manager.apply()

    def floating_ip_removed(self, ri, ex_gw_port, floating_ip, fixed_ip):
        ip_cidr = str(floating_ip) + '/32'
        net = netaddr.IPNetwork(ip_cidr)
        interface_name = self.get_external_device_name(ex_gw_port['id'])

        device = ip_lib.IPDevice(interface_name,
                                 self.conf.root_helper,
                                 namespace=ri.ns_name())
        device.addr.delete(net.version, ip_cidr)

        for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip):
            ri.iptables_manager.ipv4['nat'].remove_rule(chain, rule)
        ri.iptables_manager.apply()

    def floating_forward_rules(self, floating_ip, fixed_ip):
        return [
            ('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('float-snat', '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip))
        ]

    def router_deleted(self, context, router_id):
        """Deal with router deletion RPC message."""
        with self.sync_sem:
            if router_id in self.router_info:
                try:
                    self._router_removed(router_id)
                except Exception:
                    msg = _("Failed dealing with router "
                            "'%s' deletion RPC message")
                    LOG.debug(msg, router_id)
                    self.fullsync = True

    def routers_updated(self, context, routers):
        """Deal with routers modification and creation RPC message."""
        if not routers:
            return
        with self.sync_sem:
            try:
                self._process_routers(routers)
            except Exception:
                msg = _("Failed dealing with routers update RPC message")
                LOG.debug(msg)
                self.fullsync = True

    def _process_routers(self, routers):
        if (self.conf.external_network_bridge and
                not ip_lib.device_exists(self.conf.external_network_bridge)):
            LOG.error(
                _("The external network bridge '%s' does not exist") %
                self.conf.external_network_bridge)
            return

        target_ex_net_id = self._fetch_external_net_id()

        for r in routers:
            if not r['admin_state_up']:
                continue

            # If namespaces are disabled, only process the router associated
            # with the configured agent id.
            if (not self.conf.use_namespaces
                    and r['id'] != self.conf.router_id):
                continue

            ex_net_id = (r['external_gateway_info'] or {}).get('network_id')
            if not ex_net_id and not self.conf.handle_internal_only_routers:
                continue

            if ex_net_id and ex_net_id != target_ex_net_id:
                continue

            if r['id'] not in self.router_info:
                self._router_added(r['id'])

            ri = self.router_info[r['id']]
            ri.router = r
            self.process_router(ri)

    @periodic_task.periodic_task
    def _sync_routers_task(self, context):
        # we need to sync with router deletion RPC message
        with self.sync_sem:
            if self.fullsync:
                try:
                    if not self.conf.use_namespaces:
                        router_id = self.conf.router_id
                    else:
                        router_id = None
                    routers = self.plugin_rpc.get_routers(context, router_id)
                    self.router_info = {}
                    self._process_routers(routers)
                    self.fullsync = False
                except Exception:
                    LOG.exception(_("Failed synchronizing routers"))
                    self.fullsync = True

    def after_start(self):
        LOG.info(_("L3 agent started"))
コード例 #21
0
from quantum.openstack.common import log as logging
from quantum.openstack.common import rpc
from quantum.plugins.bigswitch.version import version_string_with_vcs

LOG = logging.getLogger(__name__)

database_opts = [
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('sql_max_retries', default=-1),
    cfg.IntOpt('reconnect_interval', default=2),
]

restproxy_opts = [
    cfg.StrOpt('servers', default='localhost:8800'),
    cfg.StrOpt('serverauth', default='username:password'),
    cfg.BoolOpt('serverssl', default=False),
    cfg.BoolOpt('syncdata', default=False),
    cfg.IntOpt('servertimeout', default=10),
]

cfg.CONF.register_opts(database_opts, "DATABASE")
cfg.CONF.register_opts(restproxy_opts, "RESTPROXY")

# The following are used to invoke the API on the external controller
NET_RESOURCE_PATH = "/tenants/%s/networks"
PORT_RESOURCE_PATH = "/tenants/%s/networks/%s/ports"
NETWORKS_PATH = "/tenants/%s/networks/%s"
PORTS_PATH = "/tenants/%s/networks/%s/ports/%s"
ATTACHMENT_PATH = "/tenants/%s/networks/%s/ports/%s/attachment"
SUCCESS_CODES = range(200, 207)
FAILURE_CODES = [
コード例 #22
0
ファイル: config.py プロジェクト: pulse-vadc/quantum
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('sql_max_retries', default=-1),
    cfg.IntOpt('reconnect_interval', default=2),
]

ovs_opts = [
    cfg.StrOpt('integration_bridge', default='br-int'),
    cfg.StrOpt('tunnel_bridge', default='br-tun'),
    cfg.StrOpt('local_ip', default='10.0.0.3'),
    cfg.ListOpt('bridge_mappings',
                default=DEFAULT_BRIDGE_MAPPINGS,
                help="List of <physical_network>:<bridge>"),
    cfg.ListOpt('network_vlan_ranges',
                default=DEFAULT_VLAN_RANGES,
                help="List of <physical_network>:<vlan_min>:<vlan_max> "
                "or <physical_network>"),
    cfg.ListOpt('tunnel_id_ranges',
                default=DEFAULT_TUNNEL_RANGES,
                help="List of <tun_min>:<tun_max>"),
]

agent_opts = [
    cfg.IntOpt('polling_interval', default=2),
    cfg.StrOpt('root_helper', default='sudo'),
    cfg.BoolOpt('rpc', default=True),
]

cfg.CONF.register_opts(database_opts, "DATABASE")
cfg.CONF.register_opts(ovs_opts, "OVS")
cfg.CONF.register_opts(agent_opts, "AGENT")
コード例 #23
0
            help='SSL cert file (valid only if SSL enabled)'),
 cfg.StrOpt('kombu_ssl_ca_certs',
            default='',
            help=('SSL certification authority file '
                  '(valid only if SSL enabled)')),
 cfg.StrOpt('rabbit_host',
            default='localhost',
            help='The RabbitMQ broker address where a single node is used'),
 cfg.IntOpt('rabbit_port',
            default=5672,
            help='The RabbitMQ broker port where a single node is used'),
 cfg.ListOpt('rabbit_hosts',
             default=['$rabbit_host:$rabbit_port'],
             help='RabbitMQ HA cluster host:port pairs'),
 cfg.BoolOpt('rabbit_use_ssl',
             default=False,
             help='connect over SSL for RabbitMQ'),
 cfg.StrOpt('rabbit_userid', default='guest', help='the RabbitMQ userid'),
 cfg.StrOpt('rabbit_password',
            default='guest',
            help='the RabbitMQ password'),
 cfg.StrOpt('rabbit_virtual_host',
            default='/',
            help='the RabbitMQ virtual host'),
 cfg.IntOpt('rabbit_retry_interval',
            default=1,
            help='how frequently to retry connecting with RabbitMQ'),
 cfg.IntOpt('rabbit_retry_backoff',
            default=2,
            help='how long to backoff for between retries when connecting '
            'to RabbitMQ'),
コード例 #24
0
ファイル: config.py プロジェクト: hongbin/quantum
vlan_opts = [
    cfg.IntOpt('vlan_start', default=1000),
    cfg.IntOpt('vlan_end', default=3000),
]

database_opts = [
    cfg.StrOpt('sql_connection', default='sqlite://'),
    cfg.IntOpt('reconnect_interval', default=2),
]

bridge_opts = [
    cfg.StrOpt('physical_interface', default='eth1'),
]

agent_opts = [
    cfg.IntOpt('polling_interval', default=2),
    cfg.StrOpt('root_helper', default='sudo'),
    cfg.BoolOpt('target_v2_api', default=False),
]


def parse(config_file):
    conf = cfg.ConfigOpts()
    conf(args=[], default_config_files=[config_file])
    conf.register_opts(vlan_opts, "VLANS")
    conf.register_opts(database_opts, "DATABASE")
    conf.register_opts(bridge_opts, "LINUX_BRIDGE")
    conf.register_opts(agent_opts, "AGENT")
    return conf