diff --git a/octavia/common/data_models.py b/octavia/common/data_models.py index 04c74350c4..f597fa51ac 100644 --- a/octavia/common/data_models.py +++ b/octavia/common/data_models.py @@ -205,12 +205,15 @@ class TLSContainer(BaseDataModel): class Amphora(BaseDataModel): def __init__(self, id=None, load_balancer_id=None, compute_id=None, - status=None, lb_network_ip=None, load_balancer=None): + status=None, lb_network_ip=None, vrrp_ip=None, + ha_ip=None, load_balancer=None): self.id = id self.load_balancer_id = load_balancer_id self.compute_id = compute_id self.status = status self.lb_network_ip = lb_network_ip + self.vrrp_ip = vrrp_ip + self.ha_ip = ha_ip self.load_balancer = load_balancer diff --git a/octavia/db/migration/alembic_migrations/versions/3e5b37a0bdb9_add_vrrp_ip_and_ha_ip_to_amphora.py b/octavia/db/migration/alembic_migrations/versions/3e5b37a0bdb9_add_vrrp_ip_and_ha_ip_to_amphora.py new file mode 100644 index 0000000000..05f77614ae --- /dev/null +++ b/octavia/db/migration/alembic_migrations/versions/3e5b37a0bdb9_add_vrrp_ip_and_ha_ip_to_amphora.py @@ -0,0 +1,40 @@ +# Copyright 2015 Rackspace +# +# 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. + +"""Add vrrp_ip and ha_ip to amphora + +Revision ID: 3e5b37a0bdb9 +Revises: 256852d5ff7c +Create Date: 2015-03-24 18:17:36.998604 + +""" + +# revision identifiers, used by Alembic. +revision = '3e5b37a0bdb9' +down_revision = '92fe9857279' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column(u'amphora', + sa.Column(u'vrrp_ip', sa.String(64), nullable=True)) + op.add_column(u'amphora', + sa.Column(u'ha_ip', sa.String(64), nullable=True)) + + +def downgrade(): + op.drop_column(u'amphora', u'vrrp_ip') + op.drop_column(u'amphora', u'ha_ip') diff --git a/octavia/db/models.py b/octavia/db/models.py index c17e12cf77..380e2577cd 100644 --- a/octavia/db/models.py +++ b/octavia/db/models.py @@ -321,6 +321,8 @@ class Amphora(base_models.BASE): nullable=True) compute_id = sa.Column(sa.String(36), nullable=True) lb_network_ip = sa.Column(sa.String(64), nullable=True) + vrrp_ip = sa.Column(sa.String(64), nullable=True) + ha_ip = sa.Column(sa.String(64), nullable=True) status = sa.Column( sa.String(36), sa.ForeignKey("provisioning_status.name", diff --git a/octavia/network/base.py b/octavia/network/base.py index cd8518cba1..46708b4c45 100644 --- a/octavia/network/base.py +++ b/octavia/network/base.py @@ -117,7 +117,9 @@ class AbstractNetworkDriver(object): :param load_balancer: octavia.common.data_models.LoadBalancer instance :param vip: octavia.common.data_models.VIP instance - :return: octavia.common.data_models.VIP instance + :return: dict consisting of amphora_id as key and bind_ip as value. + bind_ip is the ip that the amphora should listen on to + receive traffic to load balance. :raises: PlugVIPException """ pass @@ -148,11 +150,15 @@ class AbstractNetworkDriver(object): """ @abc.abstractmethod - def unplug_network(self, amphora_id, network_id): + def unplug_network(self, amphora_id, network_id, ip_address=None): """Disconnects an existing amphora from an existing network. + If ip_address is not specificed, all the interfaces plugged on + network_id should be unplugged. + :param amphora_id: id of an amphora in the compute service :param network_id: id of a network + :param ip_address: specific ip_address to unplug :return: None :raises: UnplugNetworkException, AmphoraNotFound, NetworkNotFound """ diff --git a/octavia/tests/functional/db/test_models.py b/octavia/tests/functional/db/test_models.py index d3cd9564dd..e4ab9ef15b 100644 --- a/octavia/tests/functional/db/test_models.py +++ b/octavia/tests/functional/db/test_models.py @@ -119,6 +119,8 @@ class ModelTestMixin(object): kwargs = {'id': self.FAKE_UUID_1, 'compute_id': self.FAKE_UUID_1, 'status': constants.ACTIVE, + 'vrrp_ip': self.FAKE_IP, + 'ha_ip': self.FAKE_IP, 'lb_network_ip': self.FAKE_IP} kwargs.update(overrides) return self._insert(session, models.Amphora, kwargs) diff --git a/octavia/tests/functional/db/test_repositories.py b/octavia/tests/functional/db/test_repositories.py index 8a57a0cd92..1d66d36457 100644 --- a/octavia/tests/functional/db/test_repositories.py +++ b/octavia/tests/functional/db/test_repositories.py @@ -804,6 +804,7 @@ class LoadBalancerRepositoryTest(BaseRepositoryTest): load_balancer_id=lb.id, compute_id=self.FAKE_UUID_3, status=constants.ACTIVE, + vrrp_ip=self.FAKE_IP, lb_network_ip=self.FAKE_IP) new_lb = self.lb_repo.get(self.session, id=lb.id) self.assertIsNotNone(new_lb) @@ -825,6 +826,7 @@ class LoadBalancerRepositoryTest(BaseRepositoryTest): load_balancer_id=lb.id, compute_id=self.FAKE_UUID_3, lb_network_ip=self.FAKE_IP, + vrrp_ip=self.FAKE_IP, status=constants.ACTIVE) new_lb = self.lb_repo.get(self.session, id=lb.id) self.assertIsNotNone(new_lb) @@ -1065,7 +1067,9 @@ class AmphoraRepositoryTest(BaseRepositoryTest): amphora = self.amphora_repo.create(self.session, id=amphora_id, compute_id=self.FAKE_UUID_3, status=constants.ACTIVE, - lb_network_ip=self.FAKE_IP) + lb_network_ip=self.FAKE_IP, + vrrp_ip=self.FAKE_IP, + ha_ip=self.FAKE_IP) return amphora def test_get(self): diff --git a/specs/version0.5/network-driver-interface.rst b/specs/version0.5/network-driver-interface.rst index 62ebeb82b0..88f2535563 100644 --- a/specs/version0.5/network-driver-interface.rst +++ b/specs/version0.5/network-driver-interface.rst @@ -47,6 +47,19 @@ Existing data model: * network_id - (neutron subnet) * port_id - (neutron port) +* class Amphora + * load_balancer_id + * compute_id + * lb_network_ip + * status + * vrrp_ip - if an active/passive topology, this is the ip where the vrrp + communication between peers happens + * ha_ip - this is the highly available IP. In an active/passive topology + it most likely exists on the MASTER amphora and on failure + it will be raised on the SLAVE amphora. In an active/active + topology it may exist on both amphorae. In the end, it is up + to the amphora driver to decide how to use this. + New data model: * class Interface @@ -90,7 +103,7 @@ class AbstractNetworkDriver ids and the vip data model. * vip = instance of a VIP - * returns VIP instance + * returns list of Amphora * raises PlugVIPException * unplug_vip(loadbalancer, vip) @@ -130,11 +143,13 @@ class AbstractNetworkDriver * returns Interface instance * raises PlugNetworkException, AmphoraNotFound, NetworkNotFound -* unplug_network(amphora_id, network_id) +* unplug_network(amphora_id, network_id, ip_address=None) - * Disconnects an existing amphora from an existing network. + * Disconnects an existing amphora from an existing network. If ip_address + is not specified then all interfaces on that network will be unplugged. * amphora = id of an amphora in the compute service to unplug * network_id = id of network to unplug amphora + * ip_address = ip address of interface to unplug * returns None * raises UnplugNetworkException, AmphoraNotFound, NetworkNotFound