From 701a0b8fefaaf5707d6b32d246de52cb6ddfb9c9 Mon Sep 17 00:00:00 2001 From: Brian Matheson Date: Wed, 27 May 2015 10:36:12 -0400 Subject: [PATCH] Add support for PLUMgrid via Ansible playbook Support Compass OpenStack installation with integrated PLUMgrid Open Networking Suite. PLUMgrid ONS is a comprehensive software-only networking solution for OpenStack which integrates with Neutron. The current implementation supports OpenStack Juno with a single controller. * add role for core plumgrid software * add role for plugin to neutron * add single-controller playbook to include plumgrid roles Change-Id: I4c320e9282bcafe450556e70020505fdb5aaf396 --- .../single-controller.yml | 35 + ansible/roles/plumgrid-plugin/tasks/main.yml | 148 ++++ .../plumgrid-plugin/templates/plumgrid.ini | 14 + .../templates/plumgrid_plugin.py | 811 ++++++++++++++++++ .../plumgrid-plugin/templates/plumlib.filters | 23 + .../plumgrid-plugin/templates/plumlib.py | 118 +++ ansible/roles/plumgrid/tasks/main.yml | 156 ++++ ansible/roles/plumgrid/templates/default.conf | 143 +++ .../roles/plumgrid/templates/keepalived.conf | 30 + .../roles/plumgrid/templates/plumgrid.conf | 10 + ansible/roles/plumgrid/templates/qemu.conf | 27 + 11 files changed, 1515 insertions(+) create mode 100644 ansible/openstack_juno_plumgrid/single-controller.yml create mode 100644 ansible/roles/plumgrid-plugin/tasks/main.yml create mode 100644 ansible/roles/plumgrid-plugin/templates/plumgrid.ini create mode 100644 ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py create mode 100644 ansible/roles/plumgrid-plugin/templates/plumlib.filters create mode 100644 ansible/roles/plumgrid-plugin/templates/plumlib.py create mode 100644 ansible/roles/plumgrid/tasks/main.yml create mode 100644 ansible/roles/plumgrid/templates/default.conf create mode 100644 ansible/roles/plumgrid/templates/keepalived.conf create mode 100644 ansible/roles/plumgrid/templates/plumgrid.conf create mode 100644 ansible/roles/plumgrid/templates/qemu.conf diff --git a/ansible/openstack_juno_plumgrid/single-controller.yml b/ansible/openstack_juno_plumgrid/single-controller.yml new file mode 100644 index 0000000..5551a19 --- /dev/null +++ b/ansible/openstack_juno_plumgrid/single-controller.yml @@ -0,0 +1,35 @@ +--- +- hosts: controller + sudo: True + roles: + - common + - database + - mq + - keystone + - nova-controller + - neutron-controller + - dashboard + - cinder-controller + - glance + - plumgrid + - plumgrid-plugin + +- hosts: network + sudo: True + roles: + - common + - plumgrid + +- hosts: storage + sudo: True + roles: + - common + - cinder-volume + +- hosts: compute + sudo: True + roles: + - common + - nova-compute + - neutron-compute + - plumgrid diff --git a/ansible/roles/plumgrid-plugin/tasks/main.yml b/ansible/roles/plumgrid-plugin/tasks/main.yml new file mode 100644 index 0000000..7784be0 --- /dev/null +++ b/ansible/roles/plumgrid-plugin/tasks/main.yml @@ -0,0 +1,148 @@ +# +# Copyright (c) 2012-2015, PLUMgrid, http://plumgrid.com +# + +# Create a PLUMgrid sources.list +- name: Create plumgrid sources.list + lineinfile: + dest: /etc/apt/sources.list.d/plumgrid.list + line: "deb {{ plumgrid_repo }}/plumgrid ./" + state: present + create: yes + +# Point to LCM repo create a PLUMgrid sources.list +- name: Add plumgrid-images to repo + lineinfile: + dest: /etc/apt/sources.list.d/plumgrid.list + line: "deb {{ plumgrid_repo }}/plumgrid-images ./" + state: present + +# Update repositories +- name: Running apt-update + apt: + update_cache: yes + +# Install package neutron-plugin-plumgrid +- name: Install neutron-plugin-plumgrid + apt: + name: neutron-plugin-plumgrid + state: present + +# Install package plumgrid-pythonlib +- name: Install plumgrid-pythonlib + apt: + name: plumgrid-pythonlib + state: present + +# Modify template fies +- name: Setup plumgrid.ini + template: > + src=plumgrid.ini + dest=/etc/neutron/plugins/plumgrid/plumgrid.ini + owner={{ system_group }} + group={{ system_user }} + +- name: Replace plugin.ini reference + replace: + dest: /etc/default/neutron-server + regexp: "^NEUTRON_PLUGIN_CONFIG.*" + replace: "NEUTRON_PLUGIN_CONFIG=\"/etc/neutron/plugins/plumgrid/plumgrid.ini\"" + +# Modify neutron configuration +- name: Add plumlib template + template: > + src=plumlib.py + dest=/usr/lib/python2.7/dist-packages/neutron/plugins/plumgrid/drivers/plumlib.py + owner={{ system_group }} + group={{ system_user }} + +- name: Replace plugin with Plumgrid + replace: + dest: /etc/neutron/neutron.conf + regexp: '^core_plugin.*' + replace: 'core_plugin = neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin.NeutronPluginPLUMgridV2' + +- name: Replace mysql connection spec + replace: + dest: /etc/neutron/neutron.conf + regexp: '^connection.*' + replace: 'connection = mysql://neutron:{{ NEUTRON_DBPASS }}@{{ db_host }}/ovs_neutron' + +- name: Comment service_plugins + replace: + dest: /etc/neutron/neutron.conf + regexp: '^service_plugins' + replace: '#service_plugins' + +- name: Update nova.conf + lineinfile: + dest: "/etc/nova/nova.conf" + insertafter: "DEFAULT" + state: present + create: yes + line: "{{ item }}" + with_items: + - libvirt_cpu_mode=none + - libvirt_vif_type=ethernet + - scheduler_driver=nova.scheduler.filter_scheduler.FilterScheduler + +- name: Add plumgrid_plugin template + template: > + src=plumgrid_plugin.py + dest=/usr/lib/python2.7/dist-packages/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py + owner={{ system_group }} + group={{ system_user }} + +- name: Add plumlib filters + template: > + src=plumlib.filters + dest=/etc/neutron/rootwrap.d/plumlib.filters + owner={{ system_group }} + group={{ system_user }} + +- name: Update Plumlib authentication + replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: '#admin_user = admin_username' + replace: 'admin_user = neutron' + +- replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: '#admin_password = admin_password' + replace: 'admin_password = {{ neutron_service_password }}' + +- replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: '#auth_uri = http://127.0.0.1:35357/v2.0/' + replace: 'auth_uri = http://{{ internal_lb_vip_address }}:5000/v2.0' + +- replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: '#admin_tenant_name = admin_tenant_name' + replace: 'admin_tenant_name = service' + +# Enable Metadata +- name: Enable Metadata + replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: 'enable_pg_metadata = False' + replace: 'enable_pg_metadata = True' + when: enable_pg_metadata == True + +- name: Enable Metadata mode + replace: + dest: /etc/neutron/plugins/plumgrid/plumlib.ini + regexp: 'metadata_mode = tunnel' + replace: 'metadata_mode = local' + when: enable_pg_metadata == True + +- name: Replace plugin config file + replace: + dest: /etc/init/neutron-server.conf + regexp: '/etc/neutron/plugins/ml2/ml2_conf.ini' + replace: '/etc/neutron/plugins/plumgrid/plumgrid.ini' + +- name: Start neutron server + service: name=neutron-server state=restarted + register: service_started + failed_when: "'msg' in service_started and 'FAIL' in service_started.msg|upper" diff --git a/ansible/roles/plumgrid-plugin/templates/plumgrid.ini b/ansible/roles/plumgrid-plugin/templates/plumgrid.ini new file mode 100644 index 0000000..49d6ce5 --- /dev/null +++ b/ansible/roles/plumgrid-plugin/templates/plumgrid.ini @@ -0,0 +1,14 @@ +# Config file for Neutron PLUMgrid Plugin + +[plumgriddirector] +# This line should be pointing to the PLUMgrid Director, +# for the PLUMgrid platform. +director_server={{ pg_vip }} +director_server_port=443 +# Authentification parameters for the Director. +# These are the admin credentials to manage and control +# the PLUMgrid Director server. +username=plumgrid +password=plumgrid +servertimeout=70 +connection = mysql://neutron:{{ neutron_container_mysql_password }}@{{ internal_lb_vip_address }}/neutron?charset=utf8 diff --git a/ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py b/ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py new file mode 100644 index 0000000..dde32bb --- /dev/null +++ b/ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py @@ -0,0 +1,811 @@ +# Copyright 2013 PLUMgrid, Inc. All Rights Reserved. +# +# 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. +# +# @author: Fawad Khaliq, fawad@plumgrid.com, PLUMgrid, Inc. + +""" +Neutron Plug-in for PLUMgrid Virtual Networking Infrastructure (VNI) +This plugin will forward authenticated REST API calls +to the PLUMgrid Network Management System called Director +""" + +import netaddr +from oslo.config import cfg +from sqlalchemy.orm import exc as sa_exc + +from neutron.api.v2 import attributes +from neutron.common import constants +from neutron.common import utils +from neutron.db import db_base_plugin_v2 +from neutron.db import external_net_db +from neutron.db import extraroute_db +from neutron.db import l3_db +from neutron.db import portbindings_db +from neutron.db import quota_db # noqa +from neutron.db import securitygroups_db +from neutron.extensions import portbindings +from neutron.extensions import extraroute +from neutron.extensions import securitygroup as sec_grp +from neutron.openstack.common import importutils +from neutron.openstack.common import log as logging +from neutron.plugins.plumgrid.common import exceptions as plum_excep +from neutron.plugins.plumgrid.plumgrid_plugin.plugin_ver import VERSION + +LOG = logging.getLogger(__name__) + +director_server_opts = [ + cfg.StrOpt('director_server', default='localhost', + help=_("PLUMgrid Director server to connect to")), + cfg.StrOpt('director_server_port', default='8080', + help=_("PLUMgrid Director server port to connect to")), + cfg.StrOpt('username', default='username', + help=_("PLUMgrid Director admin username")), + cfg.StrOpt('password', default='password', secret=True, + help=_("PLUMgrid Director admin password")), + cfg.IntOpt('servertimeout', default=5, + help=_("PLUMgrid Director server timeout")), + cfg.StrOpt('driver', + default="neutron.plugins.plumgrid.drivers.plumlib.Plumlib", + help=_("PLUMgrid Driver")), ] + +cfg.CONF.register_opts(director_server_opts, "plumgriddirector") + + +class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2, + external_net_db.External_net_db_mixin, + extraroute_db.ExtraRoute_db_mixin, + l3_db.L3_NAT_db_mixin, + portbindings_db.PortBindingMixin, + securitygroups_db.SecurityGroupDbMixin): + + supported_extension_aliases = ["binding", "external-net", "provider", + "quotas", "router", "security-group", "extraroute"] + + binding_view = "extension:port_binding:view" + binding_set = "extension:port_binding:set" + + def __init__(self): + LOG.info(_('Neutron PLUMgrid Director: Starting Plugin')) + + super(NeutronPluginPLUMgridV2, self).__init__() + self.plumgrid_init() + + LOG.debug(_('Neutron PLUMgrid Director: Neutron server with ' + 'PLUMgrid Plugin has started')) + + def plumgrid_init(self): + """PLUMgrid initialization.""" + director_plumgrid = cfg.CONF.plumgriddirector.director_server + director_port = cfg.CONF.plumgriddirector.director_server_port + director_admin = cfg.CONF.plumgriddirector.username + director_password = cfg.CONF.plumgriddirector.password + timeout = cfg.CONF.plumgriddirector.servertimeout + plum_driver = cfg.CONF.plumgriddirector.driver + + # PLUMgrid Director info validation + LOG.info(_('Neutron PLUMgrid Director: %s'), director_plumgrid) + self._plumlib = importutils.import_object(plum_driver) + self._plumlib.director_conn(director_plumgrid, director_port, timeout, + director_admin, director_password) + + def create_network(self, context, network): + """Create Neutron network. + + Creates a PLUMgrid-based bridge. + """ + + LOG.debug(_('Neutron PLUMgrid Director: create_network() called')) + + # Plugin DB - Network Create and validation + tenant_id = self._get_tenant_id_for_create(context, + network["network"]) + self._network_admin_state(network) + + with context.session.begin(subtransactions=True): + net_db = super(NeutronPluginPLUMgridV2, + self).create_network(context, network) + # Propagate all L3 data into DB + self._process_l3_create(context, net_db, network['network']) + self._ensure_default_security_group(context, tenant_id) + + try: + LOG.debug(_('PLUMgrid Library: create_network() called')) + self._plumlib.create_network(tenant_id, net_db, network) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Return created network + return net_db + + def update_network(self, context, net_id, network): + """Update Neutron network. + + Updates a PLUMgrid-based bridge. + """ + + LOG.debug(_("Neutron PLUMgrid Director: update_network() called")) + self._network_admin_state(network) + tenant_id = self._get_tenant_id_for_create(context, network["network"]) + + with context.session.begin(subtransactions=True): + # Plugin DB - Network Update + net_db = super( + NeutronPluginPLUMgridV2, self).update_network(context, + net_id, network) + self._process_l3_update(context, net_db, network['network']) + + try: + LOG.debug(_("PLUMgrid Library: update_network() called")) + self._plumlib.update_network(tenant_id, net_id, network) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Return updated network + return net_db + + def delete_network(self, context, net_id): + """Delete Neutron network. + + Deletes a PLUMgrid-based bridge. + """ + + LOG.debug(_("Neutron PLUMgrid Director: delete_network() called")) + net_db = super(NeutronPluginPLUMgridV2, + self).get_network(context, net_id) + + with context.session.begin(subtransactions=True): + # Plugin DB - Network Delete + super(NeutronPluginPLUMgridV2, self).delete_network(context, + net_id) + + try: + LOG.debug(_("PLUMgrid Library: update_network() called")) + self._plumlib.delete_network(net_db, net_id) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + @utils.synchronized('plumlib', external=True) + def create_port(self, context, port): + """Create Neutron port. + + Creates a PLUMgrid-based port on the specific Virtual Network + Function (VNF). + """ + LOG.debug(_("Neutron PLUMgrid Director: create_port() called")) + + # Port operations on PLUMgrid Director is an automatic operation + # from the VIF driver operations in Nova. + # It requires admin_state_up to be True + + port["port"]["admin_state_up"] = True + port_data = port["port"] + + with context.session.begin(subtransactions=True): + # Plugin DB - Port Create and Return port + port_db = super(NeutronPluginPLUMgridV2, self).create_port(context, + port) + # Update port security + port_data.update(port_db) + + self._ensure_default_security_group_on_port(context, port) + + port_data[sec_grp.SECURITYGROUPS] = ( + self._get_security_groups_on_port(context, port)) + + self._process_port_create_security_group( + context, port_db, port_data[sec_grp.SECURITYGROUPS]) + + self._process_portbindings_create_and_update(context, + port_data, port_db) + + device_id = port_db["device_id"] + if port_db["device_owner"] == constants.DEVICE_OWNER_ROUTER_GW: + router_db = self._get_router(context, device_id) + else: + router_db = None + + try: + LOG.debug(_("PLUMgrid Library: create_port() called")) + self._plumlib.create_port(port_db, router_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Plugin DB - Port Create and Return port + return self._port_viftype_binding(context, port_db) + + @utils.synchronized('plumlib', external=True) + def update_port(self, context, port_id, port): + """Update Neutron port. + + Updates a PLUMgrid-based port on the specific Virtual Network + Function (VNF). + """ + LOG.debug(_("Neutron PLUMgrid Director: update_port() called")) + + with context.session.begin(subtransactions=True): + # Plugin DB - Port Create and Return port + port_db = super(NeutronPluginPLUMgridV2, self).update_port( + context, port_id, port) + device_id = port_db["device_id"] + if port_db["device_owner"] == constants.DEVICE_OWNER_ROUTER_GW: + router_db = self._get_router(context, device_id) + else: + router_db = None + + if (self._check_update_deletes_security_groups(port) or + self._check_update_has_security_groups(port)): + self._delete_port_security_group_bindings(context, + port_db["id"]) + sg_ids = self._get_security_groups_on_port(context, port) + self._process_port_create_security_group(context, + port_db, + sg_ids) + + self._process_portbindings_create_and_update(context, + port['port'], + port_db) + + try: + LOG.debug(_("PLUMgrid Library: create_port() called")) + self._plumlib.update_port(port_db, router_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Plugin DB - Port Update + return self._port_viftype_binding(context, port_db) + + @utils.synchronized('plumlib', external=True) + def delete_port(self, context, port_id, l3_port_check=True): + """Delete Neutron port. + + Deletes a PLUMgrid-based port on the specific Virtual Network + Function (VNF). + """ + + LOG.debug(_("Neutron PLUMgrid Director: delete_port() called")) + + with context.session.begin(subtransactions=True): + # Plugin DB - Port Create and Return port + port_db = super(NeutronPluginPLUMgridV2, + self).get_port(context, port_id) + router_ids = self.disassociate_floatingips( + context, port_id, do_notify=False) + super(NeutronPluginPLUMgridV2, self).delete_port(context, port_id) + + if port_db["device_owner"] == constants.DEVICE_OWNER_ROUTER_GW: + device_id = port_db["device_id"] + router_db = self._get_router(context, device_id) + else: + router_db = None + try: + LOG.debug(_("PLUMgrid Library: delete_port() called")) + self._plumlib.delete_port(port_db, router_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # now that we've left db transaction, we are safe to notify + self.notify_routers_updated(context, router_ids) + + def get_port(self, context, id, fields=None): + with context.session.begin(subtransactions=True): + port_db = super(NeutronPluginPLUMgridV2, + self).get_port(context, id, fields) + + self._port_viftype_binding(context, port_db) + return self._fields(port_db, fields) + + def get_ports(self, context, filters=None, fields=None): + with context.session.begin(subtransactions=True): + ports_db = super(NeutronPluginPLUMgridV2, + self).get_ports(context, filters, fields) + for port_db in ports_db: + self._port_viftype_binding(context, port_db) + return [self._fields(port, fields) for port in ports_db] + + def create_subnet(self, context, subnet): + """Create Neutron subnet. + + Creates a PLUMgrid-based DHCP and NAT Virtual Network + Functions (VNFs). + """ + + LOG.debug(_("Neutron PLUMgrid Director: create_subnet() called")) + + with context.session.begin(subtransactions=True): + # Plugin DB - Subnet Create + net_db = super(NeutronPluginPLUMgridV2, self).get_network( + context, subnet['subnet']['network_id'], fields=None) + s = subnet['subnet'] + ipnet = netaddr.IPNetwork(s['cidr']) + + # PLUMgrid Director reserves the last IP address for GW + # when is not defined + if s['gateway_ip'] is attributes.ATTR_NOT_SPECIFIED: + gw_ip = str(netaddr.IPAddress(ipnet.last - 1)) + subnet['subnet']['gateway_ip'] = gw_ip + + # PLUMgrid reserves the first IP + if s['allocation_pools'] == attributes.ATTR_NOT_SPECIFIED: + allocation_pool = self._allocate_pools_for_subnet(context, s) + subnet['subnet']['allocation_pools'] = allocation_pool + + sub_db = super(NeutronPluginPLUMgridV2, self).create_subnet( + context, subnet) + + try: + LOG.debug(_("PLUMgrid Library: create_subnet() called")) + self._plumlib.create_subnet(sub_db, net_db, ipnet) + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return sub_db + + def delete_subnet(self, context, subnet_id): + """Delete subnet core Neutron API.""" + + LOG.debug(_("Neutron PLUMgrid Director: delete_subnet() called")) + # Collecting subnet info + sub_db = self._get_subnet(context, subnet_id) + net_id = sub_db["network_id"] + net_db = self.get_network(context, net_id) + tenant_id = net_db["tenant_id"] + + with context.session.begin(subtransactions=True): + # Plugin DB - Subnet Delete + super(NeutronPluginPLUMgridV2, self).delete_subnet( + context, subnet_id) + try: + LOG.debug(_("PLUMgrid Library: delete_subnet() called")) + self._plumlib.delete_subnet(tenant_id, net_db, net_id) + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + def update_subnet(self, context, subnet_id, subnet): + """Update subnet core Neutron API.""" + + LOG.debug(_("update_subnet() called")) + # Collecting subnet info + orig_sub_db = self._get_subnet(context, subnet_id) + + with context.session.begin(subtransactions=True): + # Plugin DB - Subnet Update + new_sub_db = super(NeutronPluginPLUMgridV2, + self).update_subnet(context, subnet_id, subnet) + ipnet = netaddr.IPNetwork(new_sub_db['cidr']) + + try: + # PLUMgrid Server does not support updating resources yet + LOG.debug(_("PLUMgrid Library: update_network() called")) + self._plumlib.update_subnet(orig_sub_db, new_sub_db, ipnet) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return new_sub_db + + def create_router(self, context, router): + """ + Create router extension Neutron API + """ + LOG.debug(_("Neutron PLUMgrid Director: create_router() called")) + + tenant_id = self._get_tenant_id_for_create(context, router["router"]) + + with context.session.begin(subtransactions=True): + + # Create router in DB + router_db = super(NeutronPluginPLUMgridV2, + self).create_router(context, router) + # Create router on the network controller + try: + # Add Router to VND + LOG.debug(_("PLUMgrid Library: create_router() called")) + self._plumlib.create_router(tenant_id, router_db) + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Return created router + return router_db + + def update_router(self, context, router_id, router): + + LOG.debug(_("Neutron PLUMgrid Director: update_router() called")) + + with context.session.begin(subtransactions=True): + router_db = super(NeutronPluginPLUMgridV2, + self).update_router(context, router_id, router) + try: + LOG.debug(_("PLUMgrid Library: update_router() called")) + self._plumlib.update_router(router_db, router_id) + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + # Return updated router + return router_db + + def delete_router(self, context, router_id): + LOG.debug(_("Neutron PLUMgrid Director: delete_router() called")) + + with context.session.begin(subtransactions=True): + orig_router = self._get_router(context, router_id) + tenant_id = orig_router["tenant_id"] + + super(NeutronPluginPLUMgridV2, self).delete_router(context, + router_id) + + try: + LOG.debug(_("PLUMgrid Library: delete_router() called")) + self._plumlib.delete_router(tenant_id, router_id) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + def add_router_interface(self, context, router_id, interface_info): + + LOG.debug(_("Neutron PLUMgrid Director: " + "add_router_interface() called")) + with context.session.begin(subtransactions=True): + # Validate args + router_db = self._get_router(context, router_id) + tenant_id = router_db['tenant_id'] + + # Create interface in DB + int_router = super(NeutronPluginPLUMgridV2, + self).add_router_interface(context, + router_id, + interface_info) + port_db = self._get_port(context, int_router['port_id']) + subnet_id = port_db["fixed_ips"][0]["subnet_id"] + subnet_db = super(NeutronPluginPLUMgridV2, + self)._get_subnet(context, subnet_id) + ipnet = netaddr.IPNetwork(subnet_db['cidr']) + + # Create interface on the network controller + try: + LOG.debug(_("PLUMgrid Library: add_router_interface() called")) + self._plumlib.add_router_interface(tenant_id, router_id, + port_db, ipnet) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return int_router + + def remove_router_interface(self, context, router_id, int_info): + + LOG.debug(_("Neutron PLUMgrid Director: " + "remove_router_interface() called")) + with context.session.begin(subtransactions=True): + # Validate args + router_db = self._get_router(context, router_id) + tenant_id = router_db['tenant_id'] + if 'port_id' in int_info: + port = self._get_port(context, int_info['port_id']) + net_id = port['network_id'] + + elif 'subnet_id' in int_info: + subnet_id = int_info['subnet_id'] + subnet = self._get_subnet(context, subnet_id) + net_id = subnet['network_id'] + + # Remove router in DB + del_int_router = super(NeutronPluginPLUMgridV2, + self).remove_router_interface(context, + router_id, + int_info) + + try: + LOG.debug(_("PLUMgrid Library: " + "remove_router_interface() called")) + self._plumlib.remove_router_interface(tenant_id, + net_id, router_id) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return del_int_router + + def create_floatingip(self, context, floatingip): + LOG.debug(_("Neutron PLUMgrid Director: create_floatingip() called")) + + try: + floating_ip = None + floating_ip = super(NeutronPluginPLUMgridV2, + self).create_floatingip(context, floatingip) + LOG.debug(_("PLUMgrid Library: create_floatingip() called")) + self._plumlib.create_floatingip(floating_ip) + + return floating_ip + except Exception as err_message: + if floating_ip is not None: + self.delete_floatingip(context, floating_ip["id"]) + raise plum_excep.PLUMgridException(err_msg=err_message) + + def update_floatingip(self, context, id, floatingip): + LOG.debug(_("Neutron PLUMgrid Director: update_floatingip() called")) + + try: + floating_ip_orig = super(NeutronPluginPLUMgridV2, + self).get_floatingip(context, id) + floating_ip = super(NeutronPluginPLUMgridV2, + self).update_floatingip(context, id, + floatingip) + LOG.debug(_("PLUMgrid Library: update_floatingip() called")) + self._plumlib.update_floatingip(floating_ip_orig, floating_ip, + id) + + return floating_ip + except Exception as err_message: + if floatingip['floatingip']['port_id']: + self.disassociate_floatingips(context, + floatingip['floatingip']['port_id'], + do_notify=False) + raise plum_excep.PLUMgridException(err_msg=err_message) + + def delete_floatingip(self, context, id): + LOG.debug(_("Neutron PLUMgrid Director: delete_floatingip() called")) + + floating_ip_orig = super(NeutronPluginPLUMgridV2, + self).get_floatingip(context, id) + try: + LOG.debug(_("PLUMgrid Library: delete_floatingip() called")) + self._plumlib.delete_floatingip(floating_ip_orig, id) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + super(NeutronPluginPLUMgridV2, self).delete_floatingip(context, id) + + def disassociate_floatingips(self, context, port_id, do_notify=True): + LOG.debug(_("Neutron PLUMgrid Director: disassociate_floatingips() " + "called")) + + try: + fip_qry = context.session.query(l3_db.FloatingIP) + floating_ip = fip_qry.filter_by(fixed_port_id=port_id).one() + + LOG.debug(_("PLUMgrid Library: disassociate_floatingips()" + " called")) + self._plumlib.disassociate_floatingips(floating_ip, port_id) + + except sa_exc.NoResultFound: + pass + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return super(NeutronPluginPLUMgridV2, + self).disassociate_floatingips( + context, port_id, do_notify=do_notify) + + def create_security_group(self, context, security_group, default_sg=False): + """Create a security group + + Create a new security group, including the default security group + """ + LOG.debug("Neutron PLUMgrid Director: create_security_group()" + " called") + + with context.session.begin(subtransactions=True): + + sg = security_group.get('security_group') + + tenant_id = self._get_tenant_id_for_create(context, sg) + if not default_sg: + self._ensure_default_security_group(context, tenant_id) + + sg_db = super(NeutronPluginPLUMgridV2, + self).create_security_group(context, security_group, + default_sg) + try: + LOG.debug("PLUMgrid Library: create_security_group()" + " called") + self._plumlib.create_security_group(sg_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return sg_db + + def update_security_group(self, context, sg_id, security_group): + """Update a security group + + Update security group name/description in Neutron and PLUMgrid + platform + """ + with context.session.begin(subtransactions=True): + sg_db = (super(NeutronPluginPLUMgridV2, + self).update_security_group(context, + sg_id, + security_group)) + if ('name' in security_group['security_group'] and + sg_db['name'] != 'default'): + try: + LOG.debug("PLUMgrid Library: update_security_group()" + " called") + self._plumlib.update_security_group(sg_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + return sg_db + + def delete_security_group(self, context, sg_id): + """Delete a security group + + Delete security group from Neutron and PLUMgrid Platform + + :param sg_id: security group ID of the rule to be removed + """ + with context.session.begin(subtransactions=True): + + sg = super(NeutronPluginPLUMgridV2, self).get_security_group( + context, sg_id) + if not sg: + raise sec_grp.SecurityGroupNotFound(id=sg_id) + + if sg['name'] == 'default' and not context.is_admin: + raise sec_grp.SecurityGroupCannotRemoveDefault() + + sec_grp_ip = sg['id'] + filters = {'security_group_id': [sec_grp_ip]} + if super(NeutronPluginPLUMgridV2, + self)._get_port_security_group_bindings(context, + filters): + raise sec_grp.SecurityGroupInUse(id=sec_grp_ip) + + sec_db = super(NeutronPluginPLUMgridV2, + self).delete_security_group(context, sg_id) + try: + LOG.debug("PLUMgrid Library: delete_security_group()" + " called") + self._plumlib.delete_security_group(sg) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return sec_db + + def create_security_group_rule(self, context, security_group_rule): + """Create a security group rule + + Create a security group rule in Neutron and PLUMgrid Platform + """ + LOG.debug("Neutron PLUMgrid Director: create_security_group_rule()" + " called") + bulk_rule = {'security_group_rules': [security_group_rule]} + return self.create_security_group_rule_bulk(context, bulk_rule)[0] + + def create_security_group_rule_bulk(self, context, security_group_rule): + """Create security group rules + + Create security group rules in Neutron and PLUMgrid Platform + + :param security_group_rule: list of rules to create + """ + sg_rules = security_group_rule.get('security_group_rules') + + with context.session.begin(subtransactions=True): + sg_id = super(NeutronPluginPLUMgridV2, + self)._validate_security_group_rules( + context, security_group_rule) + + # Check to make sure security group exists + security_group = super(NeutronPluginPLUMgridV2, + self).get_security_group(context, + sg_id) + + if not security_group: + raise sec_grp.SecurityGroupNotFound(id=sg_id) + + # Check for duplicate rules + self._check_for_duplicate_rules(context, sg_rules) + + sec_db = (super(NeutronPluginPLUMgridV2, + self).create_security_group_rule_bulk_native( + context, security_group_rule)) + try: + LOG.debug(_("PLUMgrid Library: create_security_" + "group_rule_bulk() called")) + self._plumlib.create_security_group_rule_bulk(sec_db) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + return sec_db + + def delete_security_group_rule(self, context, sgr_id): + """Delete a security group rule + + Delete a security group rule in Neutron and PLUMgrid Platform + """ + + LOG.debug("Neutron PLUMgrid Director: delete_security_group_rule()" + " called") + + sgr = (super(NeutronPluginPLUMgridV2, + self).get_security_group_rule(context, sgr_id)) + + if not sgr: + raise sec_grp.SecurityGroupRuleNotFound(id=sgr_id) + + super(NeutronPluginPLUMgridV2, + self).delete_security_group_rule(context, sgr_id) + try: + LOG.debug("PLUMgrid Library: delete_security_" + "group_rule() called") + self._plumlib.delete_security_group_rule(sgr) + + except Exception as err_message: + raise plum_excep.PLUMgridException(err_msg=err_message) + + """ + Internal PLUMgrid Functions + """ + + def _get_plugin_version(self): + return VERSION + + def _port_viftype_binding(self, context, port): + port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_IOVISOR + port[portbindings.VIF_DETAILS] = { + # TODO(rkukura): Replace with new VIF security details + portbindings.CAP_PORT_FILTER: + 'security-group' in self.supported_extension_aliases} + return port + + def _network_admin_state(self, network): + if network["network"].get("admin_state_up") is False: + LOG.warning("Networks with admin_state_up=False are not " + "supported by PLUMgrid plugin yet.") + return network + + def _allocate_pools_for_subnet(self, context, subnet): + """Create IP allocation pools for a given subnet + + Pools are defined by the 'allocation_pools' attribute, + a list of dict objects with 'start' and 'end' keys for + defining the pool range. + Modified from Neutron DB based class + + """ + + pools = [] + # Auto allocate the pool around gateway_ip + net = netaddr.IPNetwork(subnet['cidr']) + boundary = int(netaddr.IPAddress(subnet['gateway_ip'] or net.last)) + potential_dhcp_ip = int(net.first + 1) + if boundary == potential_dhcp_ip: + first_ip = net.first + 3 + boundary = net.first + 2 + else: + first_ip = net.first + 2 + last_ip = net.last - 1 + # Use the gw_ip to find a point for splitting allocation pools + # for this subnet + split_ip = min(max(boundary, net.first), net.last) + if split_ip > first_ip: + pools.append({'start': str(netaddr.IPAddress(first_ip)), + 'end': str(netaddr.IPAddress(split_ip - 1))}) + if split_ip < last_ip: + pools.append({'start': str(netaddr.IPAddress(split_ip + 1)), + 'end': str(netaddr.IPAddress(last_ip))}) + # return auto-generated pools + # no need to check for their validity + return pools diff --git a/ansible/roles/plumgrid-plugin/templates/plumlib.filters b/ansible/roles/plumgrid-plugin/templates/plumlib.filters new file mode 100644 index 0000000..2ea6713 --- /dev/null +++ b/ansible/roles/plumgrid-plugin/templates/plumlib.filters @@ -0,0 +1,23 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# neutron/agent/linux/iptables_manager.py +# "iptables-save", ... +python: CommandFilter, python, root +ip: CommandFilter, ip, root +kill: CommandFilter, kill, root +rm: CommandFilter, rm, root +ifc_ctl: CommandFilter, /opt/pg/bin/ifc_ctl, root, ifc_ctl +neutron-ns-metadata-proxy: CommandFilter, /usr/bin/neutron-ns-metadata-proxy, root +pg-local-metadata: CommandFilter, /usr/local/bin/pg-local-metadata, pg-local-metadata, root +pg-tunnel-metadata: CommandFilter, /usr/local/bin/pg-tunnel-metadata, pg-tunnel-metadata, root +ping: RegExpFilter, /bin/ping, root, ping, -w, \d+, -c, \d+, [0-9\.]+ +ping: IpNetnsExecFilter, ping, root +ping: CommandFilter, ping, root diff --git a/ansible/roles/plumgrid-plugin/templates/plumlib.py b/ansible/roles/plumgrid-plugin/templates/plumlib.py new file mode 100644 index 0000000..b06145e --- /dev/null +++ b/ansible/roles/plumgrid-plugin/templates/plumlib.py @@ -0,0 +1,118 @@ +# Copyright 2013 PLUMgrid, Inc. All Rights Reserved. +# +# 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. +# +# @author: Fawad Khaliq, fawad@plumgrid.com, PLUMgrid, Inc. + +""" +Neutron Plug-in for PLUMgrid Virtual Networking Infrastructure (VNI) +This plugin will forward authenticated REST API calls +to the PLUMgrid Network Management System called Director +""" + +from plumgridlib import plumlib + +from neutron.openstack.common import log as logging + +LOG = logging.getLogger(__name__) + + +class Plumlib(object): + """ + Class PLUMgrid Python Library. This library is a third-party tool + needed by PLUMgrid plugin to implement all core API in Neutron. + """ + + def __init__(self): + LOG.info(_('Python PLUMgrid Library Started ')) + + def director_conn(self, director_plumgrid, director_port, timeout, + director_admin, director_password): + self.plumlib = plumlib.Plumlib(director_plumgrid, + director_port, + timeout, + director_admin, + director_password) + + def create_network(self, tenant_id, net_db, network): + self.plumlib.create_network(tenant_id, net_db, network) + + def update_network(self, tenant_id, net_id, network): + self.plumlib.update_network(tenant_id, net_id, network) + + def delete_network(self, net_db, net_id): + self.plumlib.delete_network(net_db, net_id) + + def create_subnet(self, sub_db, net_db, ipnet): + self.plumlib.create_subnet(sub_db, net_db, ipnet) + + def update_subnet(self, orig_sub_db, new_sub_db, ipnet): + self.plumlib.update_subnet(orig_sub_db, new_sub_db, ipnet) + + def delete_subnet(self, tenant_id, net_db, net_id): + self.plumlib.delete_subnet(tenant_id, net_db, net_id) + + def create_port(self, port_db, router_db): + self.plumlib.create_port(port_db, router_db) + + def update_port(self, port_db, router_db): + self.plumlib.update_port(port_db, router_db) + + def delete_port(self, port_db, router_db): + self.plumlib.delete_port(port_db, router_db) + + def create_router(self, tenant_id, router_db): + self.plumlib.create_router(tenant_id, router_db) + + def update_router(self, router_db, router_id): + self.plumlib.update_router(router_db, router_id) + + def delete_router(self, tenant_id, router_id): + self.plumlib.delete_router(tenant_id, router_id) + + def add_router_interface(self, tenant_id, router_id, port_db, ipnet): + self.plumlib.add_router_interface(tenant_id, router_id, port_db, ipnet) + + def remove_router_interface(self, tenant_id, net_id, router_id): + self.plumlib.remove_router_interface(tenant_id, net_id, router_id) + + def create_floatingip(self, floating_ip): + self.plumlib.create_floatingip(floating_ip) + + def update_floatingip(self, floating_ip_orig, floating_ip, id): + self.plumlib.update_floatingip(floating_ip_orig, floating_ip, id) + + def delete_floatingip(self, floating_ip_orig, id): + self.plumlib.delete_floatingip(floating_ip_orig, id) + + def disassociate_floatingips(self, floating_ip, port_id): + self.plumlib.disassociate_floatingips(floating_ip, port_id) + + def create_security_group(self, sg_db): + self.plumlib.create_security_group(sg_db) + + def update_security_group(self, sg_db): + self.plumlib.update_security_group(sg_db) + + def delete_security_group(self, sg_db): + self.plumlib.delete_security_group(sg_db) + + def create_security_group_rule(self, sg_rule_db): + self.plumlib.create_security_group_rule(sg_rule_db) + + def create_security_group_rule_bulk(self, sg_rule_db): + self.plumlib.create_security_group_rule_bulk(sg_rule_db) + + def delete_security_group_rule(self, sg_rule_db): + self.plumlib.delete_security_group_rule(sg_rule_db) + diff --git a/ansible/roles/plumgrid/tasks/main.yml b/ansible/roles/plumgrid/tasks/main.yml new file mode 100644 index 0000000..121f24c --- /dev/null +++ b/ansible/roles/plumgrid/tasks/main.yml @@ -0,0 +1,156 @@ +# +# Copyright (c) 2012-2015, PLUMgrid, http://plumgrid.com +# + +#- include: plumgrid_packages.yml +# when: enable_plumgrid == True + +# Create a PLUMgrid sources.list +- name: Create plumgrid sources.list + lineinfile: + dest: /etc/apt/sources.list.d/plumgrid.list + line: "deb {{ plumgrid_repo }}/plumgrid ./" + state: present + create: yes + +# Create a PLUMgrid sources.list +- name: Add plumgrid-images to repo + lineinfile: + dest: /etc/apt/sources.list.d/plumgrid.list + line: "deb {{ plumgrid_repo }}/plumgrid-images ./" + state: present + +# Copy GPG-key file to target nodes +- name: Copy Plumgrid GPG-key file + command: apt-key adv --keyserver keyserver.ubuntu.com --recv 63F65885554E46B2 + +# Update repositories +- name: Running apt-update + apt: + update_cache: yes + +# for compute hosts +- name: Create nova ifc_ctl_sudoers file + lineinfile: + dest: /etc/sudoers.d/ifc_ctl_sudoers + line: "nova ALL=(root) NOPASSWD: /opt/pg/bin/ifc_ctl_pp *" + state: present + create: yes + owner: root + mode: "644" + when: inventory_hostname in groups['compute'] + +# Install package iovisor-dkms +- name: Install iovisor + apt: + name: iovisor-dkms + state: present + force: yes + +# Install package plumgrid-lxc +- name: Install plumgrid-lxc + apt: + name: plumgrid-lxc + state: present + force: yes + +# Install package nova-network +- name: Install nova-network + apt: + name: nova-network + state: present + force: yes + when: inventory_hostname in groups['compute'] + +- name: Disable nova-network + service: + name: nova-network + enabled: no + when: inventory_hostname in groups['compute'] + +- name: Stop nova-network + service: + name: nova-network + state: stopped + when: inventory_hostname in groups['compute'] + +# Remove openvswitch +- name: Remove openvswitch + apt: + state: absent + force: yes + name: "{{ item }}" + with_items: + - openvswitch-common + - openvswitch-datapath-dkms + +# Modify template fies +- name: Setup Keepalived Config on Controller + template: + src: keepalived.conf + dest: /var/lib/libvirt/filesystems/plumgrid/etc/keepalived/keepalived.conf + when: inventory_hostname in groups['controller'] + +- name: Setup nginx Config + template: + src: default.conf + dest: /var/lib/libvirt/filesystems/plumgrid/opt/pg/sal/nginx/conf.d/default.conf + +- name: Setup plumgrid Conf + template: + src: plumgrid.conf + dest: /var/lib/libvirt/filesystems/plumgrid/opt/pg/etc/plumgrid.conf + +- name: Update qemu settings for compute hosts + template: + src: qemu.conf + dest: /etc/libvirt/qemu.conf + when: inventory_hostname in groups['compute'] + +# Update hostname +- name: Update Plumgrid hostname + replace: + dest: "/var/lib/libvirt/filesystems/plumgrid-data/conf/etc/hostname" + replace: "pg-{{ inventory_hostname }}" + regexp: "plumgrid" + +# Update hosts +- name: Update /etc/hosts + replace: + dest: "/var/lib/libvirt/filesystems/plumgrid-data/conf/etc/hosts" + replace: "pg-{{ inventory_hostname }}" + regexp: "plumgrid" + +- name: Create ifcs file + lineinfile: + dest: "/var/lib/libvirt/filesystems/plumgrid-data/conf/pg/ifcs.conf" + line: "{{ fabric_interface }} = fabric_core host" + create: yes + +- name: Add gateway int to network node + lineinfile: + dest: "/var/lib/libvirt/filesystems/plumgrid-data/conf/pg/ifcs.conf" + line: "{{ ext_interface }} = access_phys" + create: yes + when: inventory_hostname in groups['network'] + +- name: Set mtu to 1580 in config file + lineinfile: + dest: "/etc/network/interfaces" + line: " mtu 1580" + create: yes + insertafter: "^iface {{ fabric_interface }}" + +- name: Set mtu to 1580 now + command: "ifconfig {{ fabric_interface }} mtu 1580" + +- name: Ensure PLUMgrid services are started + service: + name: plumgrid + state: started + +- name: Restart libvirt-bin + service: + name: libvirt-bin + state: restarted + pattern: libvirt-bin diff --git a/ansible/roles/plumgrid/templates/default.conf b/ansible/roles/plumgrid/templates/default.conf new file mode 100644 index 0000000..5652c44 --- /dev/null +++ b/ansible/roles/plumgrid/templates/default.conf @@ -0,0 +1,143 @@ +upstream sal { + server unix:/opt/pg/tmp/sal-web.socket; + keepalive 16; +} + +upstream websocket { + server unix:/opt/pg/tmp/sal-ws.socket; + keepalive 16; +} + +upstream pgCli { + server {{ nginx_virtual_ip }}:3000; +} + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +lua_socket_log_errors off; +#lua_code_cache off; +lua_shared_dict rest_servers 16K; +lua_shared_dict apache_servers 16K; +lua_shared_dict tc_servers 16K; +init_by_lua 'lb = require "lb" +init_servers = { + ["{{ real1 }}"] = true, +{% if real2 is defined %} + ["{{ real2 }}"] = true, +{% endif %} +{% if real3 is defined %} + ["{{ real3 }}"] = true, +{% endif %} +}'; + +# Redirect http to https +server { + listen {{ nginx_virtual_ip }}:9080; + server_name $hostname; + return 301 https://$host$request_uri; +} + +server { + listen {{ nginx_virtual_ip }}:443 ssl; + ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5; + ssl_certificate /opt/pg/sal/nginx/ssl/default.crt; + ssl_certificate_key /opt/pg/sal/nginx/ssl/default.key; + #ssl_session_cache shared:SSL:10m; + #ssl_session_timeout 10m; + + server_name $hostname; + root /opt/pg/web; + index login.html; + + location /cli/ { + proxy_pass http://pgCli/; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + } + + location /vtap/ { + alias /opt/pg/vtap; + } + + # REST API calls start with /v[0-9]/, a keyword, or a capital letter. + # Note: Regular expressions have higher precedence than prefix matches + # so don't combine with /0/... + location ~ ^/(v[0-9]/|pg/|docs|api-docs|[A-Z]) { + set $active_upstream "http://sal"; + access_by_lua 'if ngx.req.get_uri_args()["server"]~=nil then + if ngx.req.get_uri_args()["server"]~=ngx.var.host then + ngx.var.active_upstream = "https://"..ngx.req.get_uri_args()["server"]..ngx.var.request_uri + end + end'; + + proxy_pass $active_upstream; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location /0/ { + set $active_upstream "http://sal"; + access_by_lua 'if ngx.req.get_uri_args()["server"]~=nil then + if ngx.req.get_uri_args()["server"]~=ngx.var.host then + ngx.var.active_upstream = "https://"..ngx.req.get_uri_args()["server"]..ngx.var.request_uri + end + end'; + + proxy_pass $active_upstream; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location /0/websocket { + set $active_upstream "http://websocket"; + access_by_lua 'if ngx.req.get_uri_args()["server"]~=nil then + if ngx.req.get_uri_args()["server"]~=ngx.var.host then + ngx.var.active_upstream = "https://"..ngx.req.get_uri_args()["server"]..ngx.var.request_uri + end + end'; + proxy_pass $active_upstream; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } +} + +server { + listen unix:/opt/pg/tmp/sal-rest.socket; + + # debug socket + listen 127.0.0.1:9080; + + location / { + set $active_upstream ""; + access_by_lua 'ngx.var.active_upstream = find_next(ngx.shared.rest_servers, {{ rest_port }})'; + proxy_pass http://$active_upstream:{{ rest_port }}; + } + + location /_debug/rest_servers { + access_by_lua 'find_next(ngx.shared.rest_servers, {{ rest_port }})'; + content_by_lua ' + for _, ip in pairs(ngx.shared.rest_servers:get_keys()) do + ngx.say(ip.."="..ngx.shared.rest_servers:get(ip)) + end + '; + } + + location /_debug/tc_servers { + access_by_lua 'find_next(ngx.shared.tc_servers, 12349)'; + content_by_lua ' + for _, ip in pairs(ngx.shared.tc_servers:get_keys()) do + ngx.say(ip.."="..ngx.shared.tc_servers:get(ip)) + end + '; + } +} diff --git a/ansible/roles/plumgrid/templates/keepalived.conf b/ansible/roles/plumgrid/templates/keepalived.conf new file mode 100644 index 0000000..b2b638d --- /dev/null +++ b/ansible/roles/plumgrid/templates/keepalived.conf @@ -0,0 +1,30 @@ +global_defs { + router_id {{ hostname }} +} + +vrrp_script chk_nginx { + script "killall -0 nginx" + interval 2 +} + +vrrp_instance nos { + virtual_router_id {{ keepalived_router_id }} + + # for electing MASTER, highest priority wins. + priority {{ keepalived_priority }} + state BACKUP + nopreempt + + interface {{ management_bridge }} + + virtual_ipaddress { + {{ pg_vip }} dev {{ management_bridge }} label {{ management_bridge }}:1 + } + track_script { + chk_nginx + } + authentication { + auth_type PASS + auth_pass {{ keepalived_password }} + } +} diff --git a/ansible/roles/plumgrid/templates/plumgrid.conf b/ansible/roles/plumgrid/templates/plumgrid.conf new file mode 100644 index 0000000..6fa3cc0 --- /dev/null +++ b/ansible/roles/plumgrid/templates/plumgrid.conf @@ -0,0 +1,10 @@ +plumgrid_ip={{ plumgrid_ip }} +plumgrid_port={{ plumgrid_port }} +mgmt_dev={{ management_bridge }} +label={{ inventory_hostname }} +plumgrid_rsync_port=2222 +plumgrid_rest_addr=0.0.0.0:{{ rest_port }} +fabric_mode={{ fabric_mode }} +start_plumgrid_iovisor=yes +start_plumgrid=`/opt/pg/scripts/pg_is_director.sh $plumgrid_ip` +location= diff --git a/ansible/roles/plumgrid/templates/qemu.conf b/ansible/roles/plumgrid/templates/qemu.conf new file mode 100644 index 0000000..d486a79 --- /dev/null +++ b/ansible/roles/plumgrid/templates/qemu.conf @@ -0,0 +1,27 @@ +# This file is managed by Managed by Ansible + +# This is the basic set of devices allowed / required by +# all virtual machines. +# +cgroup_device_acl = [ + "/dev/null", "/dev/full", "/dev/zero", + "/dev/random", "/dev/urandom", + "/dev/ptmx", "/dev/kvm", "/dev/kqemu", + "/dev/rtc","/dev/hpet", "/dev/vfio/vfio", + "/dev/net/tun" +] + +# If clear_emulator_capabilities is enabled, libvirt will drop all +# privileged capabilities of the QEmu/KVM emulator. This is enabled by +# default. +clear_emulator_capabilities=0 + +# The user for QEMU processes run by the system instance. It can be +# specified as a user name or as a user id. The qemu driver will try to +# parse this value first as a name and then, if the name doesn't exist, +# as a user id. +# +user="root" + +# The group for QEMU processes run by the system instance. +group="root"