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
This commit is contained in:
parent
70360bca6a
commit
701a0b8fef
35
ansible/openstack_juno_plumgrid/single-controller.yml
Normal file
35
ansible/openstack_juno_plumgrid/single-controller.yml
Normal file
@ -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
|
148
ansible/roles/plumgrid-plugin/tasks/main.yml
Normal file
148
ansible/roles/plumgrid-plugin/tasks/main.yml
Normal file
@ -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"
|
14
ansible/roles/plumgrid-plugin/templates/plumgrid.ini
Normal file
14
ansible/roles/plumgrid-plugin/templates/plumgrid.ini
Normal file
@ -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
|
811
ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py
Normal file
811
ansible/roles/plumgrid-plugin/templates/plumgrid_plugin.py
Normal file
@ -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
|
23
ansible/roles/plumgrid-plugin/templates/plumlib.filters
Normal file
23
ansible/roles/plumgrid-plugin/templates/plumlib.filters
Normal file
@ -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
|
118
ansible/roles/plumgrid-plugin/templates/plumlib.py
Normal file
118
ansible/roles/plumgrid-plugin/templates/plumlib.py
Normal file
@ -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)
|
||||
|
156
ansible/roles/plumgrid/tasks/main.yml
Normal file
156
ansible/roles/plumgrid/tasks/main.yml
Normal file
@ -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
|
143
ansible/roles/plumgrid/templates/default.conf
Normal file
143
ansible/roles/plumgrid/templates/default.conf
Normal file
@ -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
|
||||
';
|
||||
}
|
||||
}
|
30
ansible/roles/plumgrid/templates/keepalived.conf
Normal file
30
ansible/roles/plumgrid/templates/keepalived.conf
Normal file
@ -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 }}
|
||||
}
|
||||
}
|
10
ansible/roles/plumgrid/templates/plumgrid.conf
Normal file
10
ansible/roles/plumgrid/templates/plumgrid.conf
Normal file
@ -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=
|
27
ansible/roles/plumgrid/templates/qemu.conf
Normal file
27
ansible/roles/plumgrid/templates/qemu.conf
Normal file
@ -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"
|
Loading…
x
Reference in New Issue
Block a user