Skip to content

Commit

Permalink
Merge pull request #156 from rackerlabs/PUC-370
Browse files Browse the repository at this point in the history
feat: adds initial neutron plugin
  • Loading branch information
skrobul authored Jul 22, 2024
2 parents 012dabc + be2a962 commit 60acbd3
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 18 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/containers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

strategy:
matrix:
project: [ironic]
project: [ironic, neutron]
openstack: [2023.1, 2024.1]

steps:
Expand All @@ -44,8 +44,7 @@ jobs:
- name: build and deploy container image to registry
uses: docker/build-push-action@v5
with:
context: "{{defaultContext}}:containers"
file: Dockerfile.${{ matrix.project }}
file: containers/Dockerfile.${{ matrix.project }}
build-args: OPENSTACK_VERSION=${{ matrix.openstack }}
pull: true # ensure we always have an up to date source
push: ${{ github.event_name != 'pull_request' }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ components/01-secrets/kustomization.yaml
# python virtualenv
.venv/
venv/
.python-version
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Nicholas Kuechler <[email protected]>
Micah Culpepper <[email protected]> <[email protected]>
4 changes: 2 additions & 2 deletions components/neutron/aio-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ conf:
plugins:
ml2_conf:
ml2:
# set the default ml2 backend as the logger for testing, actual deployment should override
mechanism_drivers: logger
# set the default ml2 backend to our plugin, neutron_understack
mechanism_drivers: understack
neutron:
DEFAULT:
# we aren't using neutron routers
Expand Down
2 changes: 1 addition & 1 deletion components/openstack-2023.1-jammy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ images:
neutron_metadata: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_ovn_metadata: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_server: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_server: "ghcr.io/rackerlabs/understack/neutron:2023.1-ubuntu_jammy"
neutron_rpc_server: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
neutron_netns_cleanup_cron: "docker.io/openstackhelm/neutron:2023.1-ubuntu_jammy"
Expand Down
24 changes: 12 additions & 12 deletions components/openstack-2024.1-jammy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ images:
ironic_retrive_swift_config: "docker.io/openstackhelm/heat:2024.1-ubuntu_jammy"

# neutron
neutron_db_sync: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_dhcp: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_l3: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_l2gw: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_linuxbridge_agent: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_metadata: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_ovn_metadata: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_server: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_rpc_server: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_netns_cleanup_cron: "docker.io/openstackhelm/neutron:2024.1-ubuntu_jammy"
neutron_db_sync: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_dhcp: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_l3: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_l2gw: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_linuxbridge_agent: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_metadata: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_ovn_metadata: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_openvswitch_agent: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_server: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_rpc_server: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_bagpipe_bgp: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"
neutron_netns_cleanup_cron: "ghcr.io/rackerlabs/understack/neutron:2024.1-ubuntu_jammy"

# nova
nova_api: "docker.io/openstackhelm/nova:2024.1-ubuntu_jammy"
Expand Down
7 changes: 7 additions & 0 deletions containers/Dockerfile.neutron
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# syntax=docker/dockerfile:1

ARG OPENSTACK_VERSION
FROM docker.io/openstackhelm/neutron:${OPENSTACK_VERSION}-ubuntu_jammy

COPY python/neutron-understack /tmp/neutron-understack
RUN /var/lib/openstack/bin/python -m pip install --no-input --no-index /tmp/neutron-understack
1 change: 1 addition & 0 deletions python/neutron-understack/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Understack neutron plugin
1 change: 1 addition & 0 deletions python/neutron-understack/neutron_understack/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1"
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import json
import logging
import typing
import uuid

from neutron_lib.plugins.ml2.api import MechanismDriver, NetworkContext, PortContext, SubnetContext

LOG = logging.getLogger(__name__)


def dump_context(context: typing.Union[NetworkContext, SubnetContext, PortContext]) -> dict:
# RESOURCE_ATTRIBUTE_MAP
# from neutron_lib.api.definitions import network, subnet, port, portbindings
# The properties of a NetworkContext.current are defined in network.RESOURCE_ATTRIBUTE_MAP
# The properties of a SubnetContext.current are defined in subnet.RESOURCE_ATTRIBUTE_MAP
# The properties of a PortContext.current are defined in port.RESOURCE_ATTRIBUTE_MAP
attr_map = {
NetworkContext: ("current", "original", "network_segments"),
SubnetContext: ("current", "original"),
PortContext: (
"current",
"original",
"status",
"original_status",
"network",
"binding_levels",
"original_binding_levels",
"top_bound_segment",
"original_top_bound_segment",
"bottom_bound_segment",
"original_bottom_bound_segment",
"host",
"original_host",
"vif_type",
"original_vif_type",
"vif_details",
"original_vif_details",
"segments_to_bind",
),
}
retval = {"errors": [], "other_attrs": []}
if isinstance(context, NetworkContext):
attrs_to_dump = attr_map[NetworkContext]
elif isinstance(context, SubnetContext):
attrs_to_dump = attr_map[SubnetContext]
elif isinstance(context, PortContext):
attrs_to_dump = attr_map[PortContext]
else:
retval["errors"].append(f"Error: unknown object type {type(context)}")
return retval

attrs = vars(context)
for attr in attrs:
if attr in attrs_to_dump:
try:
val = getattr(context, attr)
retval.update({attr: val})
except Exception as e:
retval["errors"].append(f"Error dumping {attr}: {str(e)}")
else:
retval["other_attrs"].append(attr)
return retval


def log_call(method: str, context: typing.Union[NetworkContext, SubnetContext, PortContext]) -> None:
data = dump_context(context)
data.update({"method": method})
try:
jsondata = json.dumps(data)
except Exception as e:
LOG.error(
"failed to dump %s object to JSON on %s call: %s",
str(context),
method,
str(e),
)
return
LOG.info("%s method called with data: %s", method, jsondata)


class UnderstackDriver(MechanismDriver):
# See MechanismDriver docs for resource_provider_uuid5_namespace
resource_provider_uuid5_namespace = uuid.UUID("6eae3046-4072-11ef-9bcf-d6be6370a162")

def initialize(self):
pass

def create_network_precommit(self, context):
log_call("create_network_precommit", context)

def create_network_postcommit(self, context):
log_call("create_network_postcommit", context)

def update_network_precommit(self, context):
log_call("update_network_precommit", context)

def update_network_postcommit(self, context):
log_call("update_network_postcommit", context)

def delete_network_precommit(self, context):
log_call("delete_network_precommit", context)

def delete_network_postcommit(self, context):
log_call("delete_network_postcommit", context)

def create_subnet_precommit(self, context):
log_call("create_subnet_precommit", context)

def create_subnet_postcommit(self, context):
log_call("create_subnet_postcommit", context)

def update_subnet_precommit(self, context):
log_call("update_subnet_precommit", context)

def update_subnet_postcommit(self, context):
log_call("update_subnet_postcommit", context)

def delete_subnet_precommit(self, context):
log_call("delete_subnet_precommit", context)

def delete_subnet_postcommit(self, context):
log_call("delete_subnet_postcommit", context)

def create_port_precommit(self, context):
log_call("create_port_precommit", context)

def create_port_postcommit(self, context):
log_call("create_port_postcommit", context)

def update_port_precommit(self, context):
log_call("update_port_precommit", context)

def update_port_postcommit(self, context):
log_call("update_port_postcommit", context)

def delete_port_precommit(self, context):
log_call("delete_port_precommit", context)

def delete_port_postcommit(self, context):
log_call("delete_port_postcommit", context)

def bind_port(self, context):
log_call("bind_port", context)

def check_vlan_transparency(self, context):
log_call("check_vlan_transparency", context)
34 changes: 34 additions & 0 deletions python/neutron-understack/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[metadata]
name = neutron-understack
author = Rackspace Technology
author_email = [email protected]
home_page = https://github.com/rackerlabs/understack
summary = Understack ML2 Neutron Driver
python_requires = >=3.10
classifier =
Development Status :: 3 - Alpha
Environment :: OpenStack
Intended Audience :: System Administrators
Intended Audience :: Information Technology
License :: OSI Approved :: Apache Software License
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
Programming Language :: Python :: 3.10


description_file =
README.rst

[options]
install_requires =
neutron-lib==3.*

packages = find:


[options.entry_points]
neutron.ml2.mechanism_drivers =
understack = neutron_understack.neutron_understack_mech:UnderstackDriver
28 changes: 28 additions & 0 deletions python/neutron-understack/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from setuptools import setup
import codecs
import os.path

# Obtaining version number using recommended approach from
# https://packaging.python.org/guides/single-sourcing-package-version/
# This avoids problems that may arise from trying to import neutron_understack while it is not installed.


def read(rel_path):
here = os.path.abspath(os.path.dirname(__file__))
with codecs.open(os.path.join(here, rel_path), "r") as fp:
return fp.read()


def get_version(rel_path):
for line in read(rel_path).splitlines():
if line.startswith("__version__"):
delim = '"' if '"' in line else "'"
return line.split(delim)[1]
else:
raise RuntimeError("Unable to find version string.")


setup(
name="neutron_understack",
version=get_version("neutron_understack/__init__.py"),
)

0 comments on commit 60acbd3

Please sign in to comment.