Implements: blueprint anti-affinity server group
https://blueprints.launchpad.net/octavia/+spec/anti-affinity Added a new column in lb table for server group id; Added a new task in compute tasks for creating server group; Added a new task in dtabase tasks to update server group id info for lb; Add server group id in create method in nova driver to support anti-affinity when creating compute instance Change-Id: If0d3a9ba1012651937a2bda9bc95ab4f4c8852d5
This commit is contained in:
parent
dd542b1080
commit
07a608f681
|
@ -231,6 +231,10 @@
|
|||
# the OpenStack services.
|
||||
# endpoint_type = publicURL
|
||||
|
||||
# Flag to enable nova anti-affinity capabilities to place amphorae on
|
||||
# different hosts
|
||||
# enable_anti_affinity = False
|
||||
|
||||
[neutron]
|
||||
# The name of the neutron service in the keystone catalog
|
||||
# service_name =
|
||||
|
|
|
@ -359,6 +359,9 @@ nova_opts = [
|
|||
'communication with the OpenStack services.')),
|
||||
cfg.StrOpt('endpoint_type', default='publicURL',
|
||||
help=_('Endpoint interface in identity service to use')),
|
||||
cfg.BoolOpt('enable_anti_affinity', default=False,
|
||||
help=_('Flag to indicate if nova anti-affinity feature is '
|
||||
'turned on.'))
|
||||
]
|
||||
|
||||
neutron_opts = [
|
||||
|
|
|
@ -139,6 +139,8 @@ LISTENER = 'listener'
|
|||
LISTENERS = 'listeners'
|
||||
LOADBALANCER = 'loadbalancer'
|
||||
LOADBALANCER_ID = 'loadbalancer_id'
|
||||
SERVER_GROUP_ID = 'server_group_id'
|
||||
ANTI_AFFINITY = 'anti-affinity'
|
||||
MEMBER = 'member'
|
||||
MEMBER_ID = 'member_id'
|
||||
COMPUTE_ID = 'compute_id'
|
||||
|
@ -166,6 +168,9 @@ CREATE_AMPHORA_FLOW = 'octavia-create-amphora-flow'
|
|||
CREATE_AMPHORA_FOR_LB_FLOW = 'octavia-create-amp-for-lb-flow'
|
||||
CREATE_HEALTH_MONITOR_FLOW = 'octavia-create-health-monitor-flow'
|
||||
CREATE_LISTENER_FLOW = 'octavia-create-listener_flow'
|
||||
PRE_CREATE_LOADBALANCER_FLOW = 'octavia-pre-create-loadbalancer-flow'
|
||||
CREATE_SERVER_GROUP_FLOW = 'octavia-create-server-group-flow'
|
||||
UPDATE_LB_SERVERGROUPID_FLOW = 'octavia-update-lb-server-group-id-flow'
|
||||
CREATE_LOADBALANCER_FLOW = 'octavia-create-loadbalancer-flow'
|
||||
CREATE_MEMBER_FLOW = 'octavia-create-member-flow'
|
||||
CREATE_POOL_FLOW = 'octavia-create-pool-flow'
|
||||
|
@ -227,7 +232,6 @@ CREATE_VRRP_SECURITY_RULES = 'octavia-create-vrrp-security-rules'
|
|||
|
||||
GENERATE_SERVER_PEM_TASK = 'GenerateServerPEMTask'
|
||||
|
||||
|
||||
# Task Names
|
||||
RELOAD_LB_AFTER_AMP_ASSOC = 'reload-lb-after-amp-assoc'
|
||||
RELOAD_LB_AFTER_PLUG_VIP = 'reload-lb-after-plug-vip'
|
||||
|
|
|
@ -310,7 +310,8 @@ class LoadBalancer(BaseDataModel):
|
|||
def __init__(self, id=None, project_id=None, name=None, description=None,
|
||||
provisioning_status=None, operating_status=None, enabled=None,
|
||||
topology=None, vip=None, listeners=None, amphorae=None,
|
||||
pools=None, vrrp_group=None):
|
||||
pools=None, vrrp_group=None, server_group_id=None):
|
||||
|
||||
self.id = id
|
||||
self.project_id = project_id
|
||||
self.name = name
|
||||
|
@ -324,6 +325,7 @@ class LoadBalancer(BaseDataModel):
|
|||
self.listeners = listeners or []
|
||||
self.amphorae = amphorae or []
|
||||
self.pools = pools or []
|
||||
self.server_group_id = server_group_id
|
||||
|
||||
|
||||
class VRRPGroup(BaseDataModel):
|
||||
|
|
|
@ -217,3 +217,11 @@ class InvalidRegex(OctaviaException):
|
|||
|
||||
class InvalidL7Rule(OctaviaException):
|
||||
message = _LE('Invalid L7 Rule: $(msg)s')
|
||||
|
||||
|
||||
class ServerGroupObjectCreateException(OctaviaException):
|
||||
message = _LE('Failed to create server group object.')
|
||||
|
||||
|
||||
class ServerGroupObjectDeleteException(OctaviaException):
|
||||
message = _LE('Failed to delete server group object.')
|
||||
|
|
|
@ -23,7 +23,7 @@ class ComputeBase(object):
|
|||
@abc.abstractmethod
|
||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||
key_name=None, sec_groups=None, network_ids=None,
|
||||
config_drive_files=None, user_data=None):
|
||||
config_drive_files=None, user_data=None, server_group_id=None):
|
||||
"""Build a new amphora.
|
||||
|
||||
:param name: Optional name for Amphora
|
||||
|
@ -40,6 +40,8 @@ class ComputeBase(object):
|
|||
:param user_data: Optional user data to pass to be exposed by the
|
||||
metadata server this can be a file type object as well or
|
||||
a string
|
||||
:param server_group_id: Optional server group id(uuid) which is used
|
||||
for anti_affinity feature
|
||||
|
||||
:raises ComputeBuildException: if compute failed to build amphora
|
||||
:returns: UUID of amphora
|
||||
|
@ -71,3 +73,21 @@ class ComputeBase(object):
|
|||
:returns: the amphora object
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_server_group(self, name, policy):
|
||||
"""Create a server group object
|
||||
|
||||
:param name: the name of the server group
|
||||
:param policy: the policy of the server group
|
||||
:returns: the server group object
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete_server_group(self, server_group_id):
|
||||
"""Delete a server group object
|
||||
|
||||
:param server_group_id: the uuid of a server group
|
||||
"""
|
||||
pass
|
||||
|
|
|
@ -29,13 +29,15 @@ class NoopManager(object):
|
|||
|
||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||
key_name=None, sec_groups=None, network_ids=None,
|
||||
config_drive_files=None, user_data=None, port_ids=None):
|
||||
config_drive_files=None, user_data=None, port_ids=None,
|
||||
server_group_id=None):
|
||||
LOG.debug("Compute %s no-op, build name %s, amphora_flavor %s, "
|
||||
"image_id %s, key_name %s, sec_groups %s, network_ids %s,"
|
||||
"config_drive_files %s, user_data %s, port_ids %s",
|
||||
"config_drive_files %s, user_data %s, port_ids %s,"
|
||||
"server_group_id %s",
|
||||
self.__class__.__name__, name, amphora_flavor, image_id,
|
||||
key_name, sec_groups, network_ids, config_drive_files,
|
||||
user_data, port_ids)
|
||||
user_data, port_ids, server_group_id)
|
||||
self.computeconfig[(name, amphora_flavor, image_id, key_name,
|
||||
user_data)] = (
|
||||
name, amphora_flavor,
|
||||
|
@ -66,6 +68,16 @@ class NoopManager(object):
|
|||
lb_network_ip='192.0.2.1'
|
||||
)
|
||||
|
||||
def create_server_group(self, name, policy):
|
||||
LOG.debug("Create Server Group %s no-op, name %s, policy %s ",
|
||||
self.__class__.__name__, name, policy)
|
||||
self.computeconfig[(name, policy)] = (name, policy, 'create')
|
||||
|
||||
def delete_server_group(self, server_group_id):
|
||||
LOG.debug("Delete Server Group %s no-op, id %s ",
|
||||
self.__class__.__name__, server_group_id)
|
||||
self.computeconfig[server_group_id] = (server_group_id, 'delete')
|
||||
|
||||
|
||||
class NoopComputeDriver(driver_base.ComputeBase):
|
||||
def __init__(self):
|
||||
|
@ -74,11 +86,13 @@ class NoopComputeDriver(driver_base.ComputeBase):
|
|||
|
||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||
key_name=None, sec_groups=None, network_ids=None,
|
||||
config_drive_files=None, user_data=None, port_ids=None):
|
||||
config_drive_files=None, user_data=None, port_ids=None,
|
||||
server_group_id=None):
|
||||
|
||||
compute_id = self.driver.build(name, amphora_flavor, image_id,
|
||||
key_name, sec_groups, network_ids,
|
||||
config_drive_files, user_data, port_ids)
|
||||
config_drive_files, user_data, port_ids,
|
||||
server_group_id)
|
||||
return compute_id
|
||||
|
||||
def delete(self, compute_id):
|
||||
|
@ -89,3 +103,9 @@ class NoopComputeDriver(driver_base.ComputeBase):
|
|||
|
||||
def get_amphora(self, compute_id):
|
||||
return self.driver.get_amphora(compute_id)
|
||||
|
||||
def create_server_group(self, name, policy):
|
||||
return self.driver.create_server_group(name, policy)
|
||||
|
||||
def delete_server_group(self, server_group_id):
|
||||
self.driver.delete_server_group(server_group_id)
|
||||
|
|
|
@ -42,10 +42,12 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
|||
region=CONF.nova.region_name,
|
||||
endpoint_type=CONF.nova.endpoint_type)
|
||||
self.manager = self._nova_client.servers
|
||||
self.server_groups = self._nova_client.server_groups
|
||||
|
||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||
key_name=None, sec_groups=None, network_ids=None,
|
||||
port_ids=None, config_drive_files=None, user_data=None):
|
||||
port_ids=None, config_drive_files=None, user_data=None,
|
||||
server_group_id=None):
|
||||
'''Create a new virtual machine.
|
||||
|
||||
:param name: optional name for amphora
|
||||
|
@ -63,6 +65,8 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
|||
:param user_data: Optional user data to pass to be exposed by the
|
||||
metadata server this can be a file type object as well or
|
||||
a string
|
||||
:param server_group_id: Optional server group id(uuid) which is used
|
||||
for anti_affinity feature
|
||||
|
||||
:raises ComputeBuildException: if nova failed to build virtual machine
|
||||
:returns: UUID of amphora
|
||||
|
@ -77,13 +81,17 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
|||
if port_ids:
|
||||
nics.extend([{"port-id": port_id} for port_id in port_ids])
|
||||
|
||||
server_group = None if server_group_id is None else {
|
||||
"group": server_group_id}
|
||||
|
||||
amphora = self.manager.create(
|
||||
name=name, image=image_id, flavor=amphora_flavor,
|
||||
key_name=key_name, security_groups=sec_groups,
|
||||
nics=nics,
|
||||
files=config_drive_files,
|
||||
userdata=user_data,
|
||||
config_drive=True
|
||||
config_drive=True,
|
||||
scheduler_hints=server_group
|
||||
)
|
||||
|
||||
return amphora.id
|
||||
|
@ -175,3 +183,36 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
|||
lb_network_ip=lb_network_ip
|
||||
)
|
||||
return response
|
||||
|
||||
def create_server_group(self, name, policy):
|
||||
"""Create a server group object
|
||||
|
||||
:param name: the name of the server group
|
||||
:param policy: the policy of the server group
|
||||
:raises: Generic exception if the server group is not created
|
||||
:returns: the server group object
|
||||
"""
|
||||
kwargs = {'name': name,
|
||||
'policies': [policy]}
|
||||
try:
|
||||
server_group_obj = self.server_groups.create(**kwargs)
|
||||
return server_group_obj
|
||||
except Exception:
|
||||
LOG.exception(_LE("Error create server group instance."))
|
||||
raise exceptions.ServerGroupObjectCreateException()
|
||||
|
||||
def delete_server_group(self, server_group_id):
|
||||
"""Delete a server group object
|
||||
|
||||
:raises: Generic exception if the server group is not deleted
|
||||
:param server_group_id: the uuid of a server group
|
||||
"""
|
||||
try:
|
||||
self.server_groups.delete(server_group_id)
|
||||
|
||||
except nova_exceptions.NotFound:
|
||||
LOG.warn(_LW("Server group instance with id: %s not found. "
|
||||
"Assuming already deleted."), server_group_id)
|
||||
except Exception:
|
||||
LOG.exception(_LE("Error delete server group instance."))
|
||||
raise exceptions.ServerGroupObjectDeleteException()
|
||||
|
|
|
@ -310,9 +310,12 @@ class ControllerWorker(base_taskflow.BaseTaskFlowEngine):
|
|||
lb = self._lb_repo.get(db_apis.get_session(),
|
||||
id=load_balancer_id)
|
||||
|
||||
store = {constants.LOADBALANCER: lb,
|
||||
constants.SERVER_GROUP_ID: lb.server_group_id}
|
||||
|
||||
delete_lb_tf = self._taskflow_load(self._lb_flows.
|
||||
get_delete_load_balancer_flow(),
|
||||
store={constants.LOADBALANCER: lb})
|
||||
store=store)
|
||||
|
||||
with tf_logging.DynamicLoggingListener(delete_lb_tf,
|
||||
log=LOG):
|
||||
|
|
|
@ -26,6 +26,7 @@ from octavia.controller.worker.tasks import network_tasks
|
|||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group('controller_worker', 'octavia.common.config')
|
||||
CONF.import_group('nova', 'octavia.common.config')
|
||||
|
||||
|
||||
class AmphoraFlows(object):
|
||||
|
@ -111,11 +112,12 @@ class AmphoraFlows(object):
|
|||
|
||||
sf_name = prefix + '-' + constants.CREATE_AMP_FOR_LB_SUBFLOW
|
||||
create_amp_for_lb_subflow = linear_flow.Flow(sf_name)
|
||||
|
||||
create_amp_for_lb_subflow.add(database_tasks.CreateAmphoraInDB(
|
||||
name=sf_name + '-' + constants.CREATE_AMPHORA_INDB,
|
||||
provides=constants.AMPHORA_ID))
|
||||
|
||||
anti_affinity = CONF.nova.enable_anti_affinity
|
||||
|
||||
if self.REST_AMPHORA_DRIVER:
|
||||
create_amp_for_lb_subflow.add(cert_task.GenerateServerPEMTask(
|
||||
name=sf_name + '-' + constants.GENERATE_SERVER_PEM,
|
||||
|
@ -126,15 +128,31 @@ class AmphoraFlows(object):
|
|||
name=sf_name + '-' + constants.UPDATE_CERT_EXPIRATION,
|
||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM)))
|
||||
|
||||
create_amp_for_lb_subflow.add(compute_tasks.CertComputeCreate(
|
||||
name=sf_name + '-' + constants.CERT_COMPUTE_CREATE,
|
||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM),
|
||||
provides=constants.COMPUTE_ID))
|
||||
if role in (constants.ROLE_BACKUP, constants.ROLE_MASTER
|
||||
) and anti_affinity:
|
||||
create_amp_for_lb_subflow.add(compute_tasks.CertComputeCreate(
|
||||
name=sf_name + '-' + constants.CERT_COMPUTE_CREATE,
|
||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM,
|
||||
constants.SERVER_GROUP_ID),
|
||||
provides=constants.COMPUTE_ID))
|
||||
else:
|
||||
create_amp_for_lb_subflow.add(compute_tasks.CertComputeCreate(
|
||||
name=sf_name + '-' + constants.CERT_COMPUTE_CREATE,
|
||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM),
|
||||
provides=constants.COMPUTE_ID))
|
||||
else:
|
||||
create_amp_for_lb_subflow.add(compute_tasks.ComputeCreate(
|
||||
name=sf_name + '-' + constants.COMPUTE_CREATE,
|
||||
requires=constants.AMPHORA_ID,
|
||||
provides=constants.COMPUTE_ID))
|
||||
|
||||
if role in (constants.ROLE_BACKUP, constants.ROLE_MASTER
|
||||
) and anti_affinity:
|
||||
create_amp_for_lb_subflow.add(compute_tasks.ComputeCreate(
|
||||
name=sf_name + '-' + constants.COMPUTE_CREATE,
|
||||
requires=(constants.AMPHORA_ID, constants.SERVER_GROUP_ID),
|
||||
provides=constants.COMPUTE_ID))
|
||||
else:
|
||||
create_amp_for_lb_subflow.add(compute_tasks.ComputeCreate(
|
||||
name=sf_name + '-' + constants.COMPUTE_CREATE,
|
||||
requires=constants.AMPHORA_ID,
|
||||
provides=constants.COMPUTE_ID))
|
||||
|
||||
create_amp_for_lb_subflow.add(database_tasks.UpdateAmphoraComputeId(
|
||||
name=sf_name + '-' + constants.UPDATE_AMPHORA_COMPUTEID,
|
||||
|
|
|
@ -31,6 +31,7 @@ from octavia.i18n import _LE
|
|||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group('controller_worker', 'octavia.common.config')
|
||||
CONF.import_group('nova', 'octavia.common.config')
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -44,18 +45,46 @@ class LoadBalancerFlows(object):
|
|||
|
||||
two spare amphorae.
|
||||
:raises InvalidTopology: Invalid topology specified
|
||||
:return: The graph flow for creating an active_standby loadbalancer.
|
||||
:return: The graph flow for creating a loadbalancer.
|
||||
"""
|
||||
# create a linear flow as a wrapper
|
||||
lf_name = constants.PRE_CREATE_LOADBALANCER_FLOW
|
||||
create_lb_flow_wrapper = linear_flow.Flow(lf_name)
|
||||
|
||||
f_name = constants.CREATE_LOADBALANCER_FLOW
|
||||
lb_create_flow = unordered_flow.Flow(f_name)
|
||||
|
||||
if topology == constants.TOPOLOGY_ACTIVE_STANDBY:
|
||||
# When we boot up amphora for an active/standby topology,
|
||||
# we should leverage the Nova anti-affinity capabilities
|
||||
# to place the amphora on different hosts, also we need to check
|
||||
# if anti-affinity-flag is enabled or not:
|
||||
anti_affinity = CONF.nova.enable_anti_affinity
|
||||
if anti_affinity:
|
||||
# we need to create a server group first
|
||||
create_lb_flow_wrapper.add(
|
||||
compute_tasks.NovaServerGroupCreate(
|
||||
name=lf_name + '-' +
|
||||
constants.CREATE_SERVER_GROUP_FLOW,
|
||||
requires=(constants.LOADBALANCER_ID),
|
||||
provides=constants.SERVER_GROUP_ID))
|
||||
|
||||
# update server group id in lb table
|
||||
create_lb_flow_wrapper.add(
|
||||
database_tasks.UpdateLBServerGroupInDB(
|
||||
name=lf_name + '-' +
|
||||
constants.UPDATE_LB_SERVERGROUPID_FLOW,
|
||||
requires=(constants.LOADBALANCER_ID,
|
||||
constants.SERVER_GROUP_ID)))
|
||||
|
||||
master_amp_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||
prefix=constants.ROLE_MASTER, role=constants.ROLE_MASTER)
|
||||
|
||||
backup_amp_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||
prefix=constants.ROLE_BACKUP, role=constants.ROLE_BACKUP)
|
||||
|
||||
lb_create_flow.add(master_amp_sf, backup_amp_sf)
|
||||
|
||||
elif topology == constants.TOPOLOGY_SINGLE:
|
||||
amphora_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||
prefix=constants.ROLE_STANDALONE,
|
||||
|
@ -66,7 +95,8 @@ class LoadBalancerFlows(object):
|
|||
"balancer."), topology)
|
||||
raise exceptions.InvalidTopology(topology=topology)
|
||||
|
||||
return lb_create_flow
|
||||
create_lb_flow_wrapper.add(lb_create_flow)
|
||||
return create_lb_flow_wrapper
|
||||
|
||||
def get_post_lb_amp_association_flow(self, prefix, topology):
|
||||
"""Reload the loadbalancer and create networking subflows for
|
||||
|
@ -109,6 +139,8 @@ class LoadBalancerFlows(object):
|
|||
:returns: The flow for deleting a load balancer
|
||||
"""
|
||||
delete_LB_flow = linear_flow.Flow(constants.DELETE_LOADBALANCER_FLOW)
|
||||
delete_LB_flow.add(compute_tasks.NovaServerGroupDelete(
|
||||
requires=constants.SERVER_GROUP_ID))
|
||||
delete_LB_flow.add(database_tasks.MarkLBAmphoraeHealthBusy(
|
||||
requires=constants.LOADBALANCER))
|
||||
delete_LB_flow.add(controller_tasks.DeleteListenersOnLB(
|
||||
|
|
|
@ -48,7 +48,8 @@ class BaseComputeTask(task.Task):
|
|||
class ComputeCreate(BaseComputeTask):
|
||||
"""Create the compute instance for a new amphora."""
|
||||
|
||||
def execute(self, amphora_id, ports=None, config_drive_files=None):
|
||||
def execute(self, amphora_id, ports=None, config_drive_files=None,
|
||||
server_group_id=None):
|
||||
"""Create an amphora
|
||||
|
||||
:returns: an amphora
|
||||
|
@ -82,7 +83,8 @@ class ComputeCreate(BaseComputeTask):
|
|||
network_ids=[CONF.controller_worker.amp_network],
|
||||
port_ids=[port.id for port in ports],
|
||||
config_drive_files=config_drive_files,
|
||||
user_data=user_data)
|
||||
user_data=user_data,
|
||||
server_group_id=server_group_id)
|
||||
|
||||
LOG.debug("Server created with id: %s for amphora id: %s",
|
||||
compute_id, amphora_id)
|
||||
|
@ -111,7 +113,8 @@ class ComputeCreate(BaseComputeTask):
|
|||
|
||||
|
||||
class CertComputeCreate(ComputeCreate):
|
||||
def execute(self, amphora_id, server_pem, ports=None):
|
||||
def execute(self, amphora_id, server_pem, ports=None,
|
||||
server_group_id=None):
|
||||
"""Create an amphora
|
||||
|
||||
:returns: an amphora
|
||||
|
@ -125,7 +128,8 @@ class CertComputeCreate(ComputeCreate):
|
|||
'/etc/octavia/certs/server.pem': server_pem,
|
||||
'/etc/octavia/certs/client_ca.pem': ca}
|
||||
return super(CertComputeCreate, self).execute(
|
||||
amphora_id, ports=ports, config_drive_files=config_drive_files)
|
||||
amphora_id, ports=ports, config_drive_files=config_drive_files,
|
||||
server_group_id=server_group_id)
|
||||
|
||||
|
||||
class DeleteAmphoraeOnLoadBalancer(BaseComputeTask):
|
||||
|
@ -177,3 +181,39 @@ class ComputeWait(BaseComputeTask):
|
|||
time.sleep(CONF.controller_worker.amp_active_wait_sec)
|
||||
|
||||
raise exceptions.ComputeWaitTimeoutException()
|
||||
|
||||
|
||||
class NovaServerGroupCreate(BaseComputeTask):
|
||||
def execute(self, loadbalancer_id):
|
||||
"""Create a server group by nova client api
|
||||
|
||||
:param loadbalancer_id: will be used for server group's name
|
||||
:param policy: will used for server group's policy
|
||||
:raises: Generic exception if the server group is not created
|
||||
:returns: server group's id
|
||||
"""
|
||||
|
||||
name = 'octavia-lb-' + loadbalancer_id
|
||||
server_group = self.compute.create_server_group(
|
||||
name, constants.ANTI_AFFINITY)
|
||||
LOG.debug("Server Group created with id: %s for load balancer id: "
|
||||
"%s", server_group.id, loadbalancer_id)
|
||||
return server_group.id
|
||||
|
||||
def revert(self, result, *args, **kwargs):
|
||||
"""This method will revert the creation of the
|
||||
|
||||
:param result: here it refers to server group id
|
||||
"""
|
||||
server_group_id = result
|
||||
LOG.warn(_LW("Reverting server group create with id:%s"),
|
||||
server_group_id)
|
||||
self.compute.delete_server_group(server_group_id)
|
||||
|
||||
|
||||
class NovaServerGroupDelete(BaseComputeTask):
|
||||
def execute(self, server_group_id):
|
||||
if server_group_id is not None:
|
||||
self.compute.delete_server_group(server_group_id)
|
||||
else:
|
||||
return
|
||||
|
|
|
@ -690,6 +690,25 @@ class MarkLBActiveInDB(BaseDatabaseTask):
|
|||
provisioning_status=constants.ERROR)
|
||||
|
||||
|
||||
class UpdateLBServerGroupInDB(BaseDatabaseTask):
|
||||
"""Update the server group id info for load balancer in DB."""
|
||||
|
||||
def execute(self, loadbalancer_id, server_group_id):
|
||||
LOG.debug("Server Group updated with id: %s for load balancer id: %s:",
|
||||
server_group_id, loadbalancer_id)
|
||||
self.loadbalancer_repo.update(db_apis.get_session(),
|
||||
id=loadbalancer_id,
|
||||
server_group_id=server_group_id)
|
||||
|
||||
def revert(self, loadbalancer_id, server_group_id, *args, **kwargs):
|
||||
LOG.warn(_LW('Reverting Server Group updated with id: %(s1)s for '
|
||||
'load balancer id: %(s2)s '),
|
||||
{'s1': server_group_id, 's2': loadbalancer_id})
|
||||
self.loadbalancer_repo.update(db_apis.get_session(),
|
||||
id=loadbalancer_id,
|
||||
server_group_id=None)
|
||||
|
||||
|
||||
class MarkLBDeletedInDB(BaseDatabaseTask):
|
||||
"""Mark the load balancer deleted in the DB.
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2016 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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_server_group_id_to_loadbalancer
|
||||
|
||||
Revision ID: 186509101b9b
|
||||
Revises: 29ff921a6eb
|
||||
Create Date: 2016-01-25 15:12:52.489652
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '186509101b9b'
|
||||
down_revision = '458c9ee2a011'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column(u'load_balancer', sa.Column(u'server_group_id',
|
||||
sa.String(36), nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
|
@ -277,6 +277,7 @@ class LoadBalancer(base_models.BASE, base_models.IdMixin,
|
|||
amphorae = orm.relationship("Amphora", uselist=True,
|
||||
backref=orm.backref("load_balancer",
|
||||
uselist=False))
|
||||
server_group_id = sa.Column(sa.String(36), nullable=True)
|
||||
|
||||
|
||||
class VRRPGroup(base_models.BASE):
|
||||
|
|
|
@ -103,7 +103,8 @@ class ModelTestMixin(object):
|
|||
'id': self.FAKE_UUID_1,
|
||||
'provisioning_status': constants.ACTIVE,
|
||||
'operating_status': constants.ONLINE,
|
||||
'enabled': True}
|
||||
'enabled': True,
|
||||
'server_group_id': self.FAKE_UUID_1}
|
||||
kwargs.update(overrides)
|
||||
return self._insert(session, models.LoadBalancer, kwargs)
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
|
|||
'operating_status': constants.OFFLINE,
|
||||
'topology': constants.TOPOLOGY_ACTIVE_STANDBY,
|
||||
'vrrp_group': None,
|
||||
'server_group_id': uuidutils.generate_uuid(),
|
||||
'project_id': uuidutils.generate_uuid()}
|
||||
vip = {'ip_address': '10.0.0.1',
|
||||
'port_id': uuidutils.generate_uuid(),
|
||||
|
@ -547,7 +548,8 @@ class ListenerRepositoryTest(BaseRepositoryTest):
|
|||
self.session, id=self.FAKE_UUID_1, project_id=self.FAKE_UUID_2,
|
||||
name="lb_name", description="lb_description",
|
||||
provisioning_status=constants.ACTIVE,
|
||||
operating_status=constants.ONLINE, enabled=True)
|
||||
operating_status=constants.ONLINE, enabled=True,
|
||||
server_group_id=self.FAKE_UUID_1)
|
||||
|
||||
def create_listener(self, listener_id, port, default_pool_id=None):
|
||||
listener = self.listener_repo.create(
|
||||
|
|
|
@ -36,15 +36,20 @@ class TestNoopComputeDriver(base.TestCase):
|
|||
self.confdrivefiles = "config_driver_files"
|
||||
self.user_data = "user_data"
|
||||
self.amphora_id = self.FAKE_UUID_1
|
||||
self.loadbalancer_id = self.FAKE_UUID_1
|
||||
self.server_group_policy = 'anti-affinity'
|
||||
self.server_group_id = self.FAKE_UUID_1
|
||||
|
||||
def build(self):
|
||||
self.driver.build(self.name, self.amphora_flavor, self.image_id,
|
||||
self.key_name, self.sec_groups, self.network_ids,
|
||||
self.confdrivefiles, self.user_data)
|
||||
self.confdrivefiles, self.user_data,
|
||||
self.server_group_id)
|
||||
|
||||
self.assertEqual((self.name, self.amphora_flavor, self.image_id,
|
||||
self.key_name, self.sec_groups, self.network_ids,
|
||||
self.config_drive_files, self.user_data, 'build'),
|
||||
self.config_drive_files, self.user_data,
|
||||
self.server_group_id, 'build'),
|
||||
self.driver.driver.computeconfig[(self.name,
|
||||
self.amphora_flavor,
|
||||
self.image_id,
|
||||
|
@ -52,7 +57,9 @@ class TestNoopComputeDriver(base.TestCase):
|
|||
self.sec_groups,
|
||||
self.network_ids,
|
||||
self.confdrivefiles,
|
||||
self.user_data)])
|
||||
self.user_data,
|
||||
self.server_group_id
|
||||
)])
|
||||
|
||||
def test_delete(self):
|
||||
self.driver.delete(self.amphora_id)
|
||||
|
@ -65,3 +72,10 @@ class TestNoopComputeDriver(base.TestCase):
|
|||
|
||||
def get_amphora(self):
|
||||
self.driver.get_amphora(self.amphora_id)
|
||||
|
||||
def test_create_server_group(self):
|
||||
self.driver.create_server_group(self.loadbalancer_id,
|
||||
self.server_group_policy)
|
||||
|
||||
def test_delete_server_group(self):
|
||||
self.driver.delete_server_group(self.server_group_id)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
import mock
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
|
@ -50,19 +51,34 @@ class TestNovaClient(base.TestCase):
|
|||
self.interface_list.fixed_ips = [mock.MagicMock()]
|
||||
self.interface_list.fixed_ips[0] = {'ip_address': '10.0.0.1'}
|
||||
|
||||
self.loadbalancer_id = uuidutils.generate_uuid()
|
||||
self.server_group_policy = constants.ANTI_AFFINITY
|
||||
self.server_group_id = uuidutils.generate_uuid()
|
||||
|
||||
self.manager = nova_common.VirtualMachineManager()
|
||||
self.manager.manager = mock.MagicMock()
|
||||
self.manager.server_groups = mock.MagicMock()
|
||||
self.manager._nova_client = mock.MagicMock()
|
||||
|
||||
self.nova_response.interface_list.side_effect = [[self.interface_list]]
|
||||
self.manager.manager.get.return_value = self.nova_response
|
||||
self.manager.manager.create.return_value = self.nova_response
|
||||
self.manager.server_groups.create.return_value = mock.Mock()
|
||||
|
||||
self.nova_response.addresses = {self.net_name: [{'addr': '10.0.0.1'}]}
|
||||
|
||||
self.nova_network = mock.Mock()
|
||||
self.nova_network.label = self.net_name
|
||||
|
||||
self.server_group_name = 'octavia-lb-' + self.loadbalancer_id
|
||||
self.server_group_kwargs = {'name': self.server_group_name,
|
||||
'policies': [self.server_group_policy]}
|
||||
|
||||
self.server_group_mock = mock.Mock()
|
||||
self.server_group_mock.name = self.server_group_name
|
||||
self.server_group_mock.policy = self.server_group_policy
|
||||
self.server_group_mock.id = self.server_group_id
|
||||
|
||||
super(TestNovaClient, self).setUp()
|
||||
|
||||
def test_build(self):
|
||||
|
@ -85,7 +101,8 @@ class TestNovaClient(base.TestCase):
|
|||
security_groups=1,
|
||||
files='Files Blah',
|
||||
userdata='Blah',
|
||||
config_drive=True)
|
||||
config_drive=True,
|
||||
scheduler_hints=None)
|
||||
|
||||
def test_bad_build(self):
|
||||
self.manager.manager.create.side_effect = Exception
|
||||
|
@ -144,3 +161,43 @@ class TestNovaClient(base.TestCase):
|
|||
self.assertEqual(self.amphora, amphora)
|
||||
self.assertTrue(self.nova_response.interface_list.called)
|
||||
self.manager._nova_client.networks.get.called_with(self.net_name)
|
||||
|
||||
def test_create_server_group(self):
|
||||
self.manager.server_groups.create.return_value = self.server_group_mock
|
||||
|
||||
sg = self.manager.create_server_group(self.server_group_name,
|
||||
self.server_group_policy)
|
||||
|
||||
self.assertEqual(sg.id, self.server_group_id)
|
||||
self.assertEqual(sg.name, self.server_group_name)
|
||||
self.assertEqual(sg.policy, self.server_group_policy)
|
||||
self.manager.server_groups.create.called_with(
|
||||
**self.server_group_kwargs)
|
||||
|
||||
def test_bad_create_server_group(self):
|
||||
self.manager.server_groups.create.side_effect = Exception
|
||||
self.assertRaises(exceptions.ServerGroupObjectCreateException,
|
||||
self.manager.create_server_group,
|
||||
self.server_group_name, self.server_group_policy)
|
||||
self.manager.server_groups.create.called_with(
|
||||
**self.server_group_kwargs)
|
||||
|
||||
def test_delete_server_group(self):
|
||||
self.manager.delete_server_group(self.server_group_id)
|
||||
self.manager.server_groups.delete.called_with(self.server_group_id)
|
||||
|
||||
def test_bad_delete_server_group(self):
|
||||
self.manager.server_groups.delete.side_effect = [
|
||||
nova_exceptions.NotFound('test_exception'), Exception]
|
||||
|
||||
# NotFound should not raise an exception
|
||||
|
||||
self.manager.delete_server_group(self.server_group_id)
|
||||
self.manager.server_groups.delete.called_with(self.server_group_id)
|
||||
|
||||
# Catch the exception for server group object delete exception
|
||||
|
||||
self.assertRaises(exceptions.ServerGroupObjectDeleteException,
|
||||
self.manager.delete_server_group,
|
||||
self.server_group_id)
|
||||
self.manager.server_groups.delete.called_with(self.server_group_id)
|
||||
|
|
|
@ -37,6 +37,7 @@ class TestEndpoint(base.TestCase):
|
|||
self.context = {}
|
||||
self.resource_updates = {}
|
||||
self.resource_id = 1234
|
||||
self.server_group_id = 3456
|
||||
|
||||
def test_create_load_balancer(self):
|
||||
self.ep.create_load_balancer(self.context, self.resource_id)
|
||||
|
|
|
@ -30,6 +30,8 @@ class TestAmphoraFlows(base.TestCase):
|
|||
def setUp(self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
cfg.CONF.set_override('enable_anti_affinity', False,
|
||||
group='nova')
|
||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||
conf = oslo_fixture.Config(cfg.CONF)
|
||||
conf.config(group="keystone_authtoken", auth_version=AUTH_VERSION)
|
||||
|
@ -89,6 +91,7 @@ class TestAmphoraFlows(base.TestCase):
|
|||
def test_get_cert_create_amphora_for_lb_flow(self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
|
||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||
|
||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
||||
|
@ -110,6 +113,7 @@ class TestAmphoraFlows(base.TestCase):
|
|||
def test_get_cert_master_create_amphora_for_lb_flow(self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
|
||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||
|
||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
||||
|
@ -128,6 +132,28 @@ class TestAmphoraFlows(base.TestCase):
|
|||
self.assertEqual(5, len(amp_flow.provides))
|
||||
self.assertEqual(1, len(amp_flow.requires))
|
||||
|
||||
def test_get_cert_master_rest_anti_affinity_create_amphora_for_lb_flow(
|
||||
self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
|
||||
cfg.CONF.set_override('enable_anti_affinity', True,
|
||||
group='nova')
|
||||
|
||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
||||
'SOMEPREFIX', constants.ROLE_MASTER)
|
||||
|
||||
self.assertIsInstance(amp_flow, flow.Flow)
|
||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||
self.assertIn(constants.SERVER_GROUP_ID, amp_flow.requires)
|
||||
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_OBJ, amp_flow.provides)
|
||||
self.assertIn(constants.SERVER_PEM, amp_flow.provides)
|
||||
|
||||
self.assertEqual(5, len(amp_flow.provides))
|
||||
self.assertEqual(2, len(amp_flow.requires))
|
||||
|
||||
def test_get_cert_backup_create_amphora_for_lb_flow(self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
|
@ -170,6 +196,27 @@ class TestAmphoraFlows(base.TestCase):
|
|||
self.assertEqual(5, len(amp_flow.provides))
|
||||
self.assertEqual(1, len(amp_flow.requires))
|
||||
|
||||
def test_get_cert_backup_rest_anti_affinity_create_amphora_for_lb_flow(
|
||||
self):
|
||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||
group='controller_worker')
|
||||
cfg.CONF.set_override('enable_anti_affinity', True,
|
||||
group='nova')
|
||||
|
||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
||||
'SOMEPREFIX', constants.ROLE_BACKUP)
|
||||
|
||||
self.assertIsInstance(amp_flow, flow.Flow)
|
||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||
self.assertIn(constants.SERVER_GROUP_ID, amp_flow.requires)
|
||||
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_OBJ, amp_flow.provides)
|
||||
self.assertIn(constants.SERVER_PEM, amp_flow.provides)
|
||||
|
||||
self.assertEqual(5, len(amp_flow.provides))
|
||||
self.assertEqual(2, len(amp_flow.requires))
|
||||
|
||||
def test_get_delete_amphora_flow(self):
|
||||
|
||||
amp_flow = self.AmpFlow.get_delete_amphora_flow()
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as oslo_fixture
|
||||
from taskflow.patterns import linear_flow as flow
|
||||
from taskflow.patterns import unordered_flow
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.common import exceptions
|
||||
|
@ -26,13 +26,14 @@ class TestLoadBalancerFlows(base.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.LBFlow = load_balancer_flows.LoadBalancerFlows()
|
||||
|
||||
conf = oslo_fixture.Config(cfg.CONF)
|
||||
conf.config(group="nova", enable_anti_affinity=False)
|
||||
super(TestLoadBalancerFlows, self).setUp()
|
||||
|
||||
def test_get_create_load_balancer_flow(self):
|
||||
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
||||
constants.TOPOLOGY_SINGLE)
|
||||
self.assertIsInstance(amp_flow, unordered_flow.Flow)
|
||||
self.assertIsInstance(amp_flow, flow.Flow)
|
||||
self.assertIn(constants.LOADBALANCER_ID, amp_flow.requires)
|
||||
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||
|
@ -42,13 +43,27 @@ class TestLoadBalancerFlows(base.TestCase):
|
|||
def test_get_create_active_standby_load_balancer_flow(self):
|
||||
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
||||
constants.TOPOLOGY_ACTIVE_STANDBY)
|
||||
self.assertIsInstance(amp_flow, unordered_flow.Flow)
|
||||
self.assertIsInstance(amp_flow, flow.Flow)
|
||||
self.assertIn(constants.LOADBALANCER_ID, amp_flow.requires)
|
||||
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_OBJ, amp_flow.provides)
|
||||
|
||||
def test_get_create_anti_affinity_active_standby_load_balancer_flow(self):
|
||||
cfg.CONF.set_override('enable_anti_affinity', True,
|
||||
group='nova')
|
||||
self._LBFlow = load_balancer_flows.LoadBalancerFlows()
|
||||
amp_flow = self._LBFlow.get_create_load_balancer_flow(
|
||||
constants.TOPOLOGY_ACTIVE_STANDBY)
|
||||
self.assertIsInstance(amp_flow, flow.Flow)
|
||||
self.assertIn(constants.LOADBALANCER_ID, amp_flow.requires)
|
||||
self.assertIn(constants.SERVER_GROUP_ID, amp_flow.provides)
|
||||
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
||||
self.assertIn(constants.COMPUTE_OBJ, amp_flow.provides)
|
||||
|
||||
def test_get_create_bogus_topology_load_balancer_flow(self):
|
||||
self.assertRaises(exceptions.InvalidTopology,
|
||||
self.LBFlow.get_create_load_balancer_flow,
|
||||
|
@ -61,9 +76,10 @@ class TestLoadBalancerFlows(base.TestCase):
|
|||
self.assertIsInstance(lb_flow, flow.Flow)
|
||||
|
||||
self.assertIn(constants.LOADBALANCER, lb_flow.requires)
|
||||
self.assertIn(constants.SERVER_GROUP_ID, lb_flow.requires)
|
||||
|
||||
self.assertEqual(0, len(lb_flow.provides))
|
||||
self.assertEqual(1, len(lb_flow.requires))
|
||||
self.assertEqual(2, len(lb_flow.requires))
|
||||
|
||||
def test_get_new_LB_networking_subflow(self):
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ from oslo_config import fixture as oslo_fixture
|
|||
from oslo_utils import uuidutils
|
||||
import six.moves.builtins as builtins
|
||||
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.common import exceptions
|
||||
from octavia.controller.worker.tasks import compute_tasks
|
||||
|
@ -35,6 +36,7 @@ COMPUTE_ID = uuidutils.generate_uuid()
|
|||
LB_NET_IP = '192.0.2.1'
|
||||
PORT_ID = uuidutils.generate_uuid()
|
||||
AUTH_VERSION = '2'
|
||||
SERVER_GRPOUP_ID = uuidutils.generate_uuid()
|
||||
|
||||
|
||||
class TestException(Exception):
|
||||
|
@ -85,7 +87,8 @@ class TestComputeTasks(base.TestCase):
|
|||
|
||||
mock_driver.build.return_value = COMPUTE_ID
|
||||
# Test execute()
|
||||
compute_id = createcompute.execute(_amphora_mock.id, ports=[_port])
|
||||
compute_id = createcompute.execute(_amphora_mock.id, ports=[_port],
|
||||
server_group_id=SERVER_GRPOUP_ID)
|
||||
|
||||
# Validate that the build method was called properly
|
||||
mock_driver.build.assert_called_once_with(
|
||||
|
@ -98,7 +101,8 @@ class TestComputeTasks(base.TestCase):
|
|||
port_ids=[PORT_ID],
|
||||
config_drive_files={'/etc/octavia/'
|
||||
'amphora-agent.conf': 'test_conf'},
|
||||
user_data=None)
|
||||
user_data=None,
|
||||
server_group_id=SERVER_GRPOUP_ID)
|
||||
|
||||
# Make sure it returns the expected compute_id
|
||||
assert(compute_id == COMPUTE_ID)
|
||||
|
@ -155,7 +159,8 @@ class TestComputeTasks(base.TestCase):
|
|||
network_ids=[AMP_NET],
|
||||
port_ids=[PORT_ID],
|
||||
config_drive_files=None,
|
||||
user_data='test_ud_conf')
|
||||
user_data='test_ud_conf',
|
||||
server_group_id=None)
|
||||
|
||||
# Make sure it returns the expected compute_id
|
||||
assert(compute_id == COMPUTE_ID)
|
||||
|
@ -199,7 +204,8 @@ class TestComputeTasks(base.TestCase):
|
|||
conf.config(group="controller_worker", amp_ssh_access_allowed=False)
|
||||
|
||||
# Test execute()
|
||||
compute_id = createcompute.execute(_amphora_mock.id, ports=[_port])
|
||||
compute_id = createcompute.execute(_amphora_mock.id, ports=[_port],
|
||||
server_group_id=SERVER_GRPOUP_ID)
|
||||
|
||||
# Validate that the build method was called properly
|
||||
mock_driver.build.assert_called_once_with(
|
||||
|
@ -212,7 +218,8 @@ class TestComputeTasks(base.TestCase):
|
|||
port_ids=[PORT_ID],
|
||||
config_drive_files={'/etc/octavia/'
|
||||
'amphora-agent.conf': 'test_conf'},
|
||||
user_data=None)
|
||||
user_data=None,
|
||||
server_group_id=SERVER_GRPOUP_ID)
|
||||
|
||||
# Make sure it returns the expected compute_id
|
||||
self.assertEqual(COMPUTE_ID, compute_id)
|
||||
|
@ -252,8 +259,9 @@ class TestComputeTasks(base.TestCase):
|
|||
m = mock.mock_open(read_data='test')
|
||||
with mock.patch.object(builtins, 'open', m, create=True):
|
||||
# Test execute()
|
||||
compute_id = createcompute.execute(_amphora_mock.id,
|
||||
'test_cert')
|
||||
compute_id = createcompute.execute(_amphora_mock.id, 'test_cert',
|
||||
server_group_id=SERVER_GRPOUP_ID
|
||||
)
|
||||
|
||||
# Validate that the build method was called properly
|
||||
mock_driver.build.assert_called_once_with(
|
||||
|
@ -268,7 +276,8 @@ class TestComputeTasks(base.TestCase):
|
|||
config_drive_files={
|
||||
'/etc/octavia/certs/server.pem': 'test_cert',
|
||||
'/etc/octavia/certs/client_ca.pem': 'test',
|
||||
'/etc/octavia/amphora-agent.conf': 'test_conf'})
|
||||
'/etc/octavia/amphora-agent.conf': 'test_conf'},
|
||||
server_group_id=SERVER_GRPOUP_ID)
|
||||
|
||||
# Make sure it returns the expected compute_id
|
||||
assert(compute_id == COMPUTE_ID)
|
||||
|
@ -355,3 +364,44 @@ class TestComputeTasks(base.TestCase):
|
|||
delete_compute.execute(_amphora_mock)
|
||||
|
||||
mock_driver.delete.assert_called_once_with(COMPUTE_ID)
|
||||
|
||||
@mock.patch('stevedore.driver.DriverManager.driver')
|
||||
def test_nova_server_group_create(self, mock_driver):
|
||||
nova_sever_group_obj = compute_tasks.NovaServerGroupCreate()
|
||||
|
||||
server_group_test_id = '6789'
|
||||
fake_server_group = mock.MagicMock()
|
||||
fake_server_group.id = server_group_test_id
|
||||
fake_server_group.policy = 'anti-affinity'
|
||||
mock_driver.create_server_group.return_value = fake_server_group
|
||||
|
||||
# Test execute()
|
||||
sg_id = nova_sever_group_obj.execute('123')
|
||||
|
||||
# Validate that the build method was called properly
|
||||
mock_driver.create_server_group.assert_called_once_with(
|
||||
'octavia-lb-123', 'anti-affinity')
|
||||
|
||||
# Make sure it returns the expected server group_id
|
||||
assert(sg_id == server_group_test_id)
|
||||
|
||||
# Test revert()
|
||||
nova_sever_group_obj.revert(sg_id)
|
||||
|
||||
# Validate that the delete_server_group method was called properly
|
||||
mock_driver.delete_server_group.assert_called_once_with(sg_id)
|
||||
nova_sever_group_obj.revert(sg_id)
|
||||
|
||||
@mock.patch('stevedore.driver.DriverManager.driver')
|
||||
def test_nova_server_group_delete_with_sever_group_id(self, mock_driver):
|
||||
nova_sever_group_obj = compute_tasks.NovaServerGroupDelete()
|
||||
sg_id = '6789'
|
||||
nova_sever_group_obj.execute(sg_id)
|
||||
mock_driver.delete_server_group.assert_called_once_with(sg_id)
|
||||
|
||||
@mock.patch('stevedore.driver.DriverManager.driver')
|
||||
def test_nova_server_group_delete_with_None(self, mock_driver):
|
||||
nova_sever_group_obj = compute_tasks.NovaServerGroupDelete()
|
||||
sg_id = None
|
||||
nova_sever_group_obj.execute(sg_id)
|
||||
self.assertFalse(mock_driver.delete_server_group.called, sg_id)
|
||||
|
|
|
@ -29,6 +29,7 @@ import octavia.tests.unit.base as base
|
|||
AMP_ID = uuidutils.generate_uuid()
|
||||
COMPUTE_ID = uuidutils.generate_uuid()
|
||||
LB_ID = uuidutils.generate_uuid()
|
||||
SERVER_GROUP_ID = uuidutils.generate_uuid()
|
||||
LB_NET_IP = '192.0.2.2'
|
||||
LISTENER_ID = uuidutils.generate_uuid()
|
||||
POOL_ID = uuidutils.generate_uuid()
|
||||
|
@ -1348,3 +1349,27 @@ class TestDatabaseTasks(base.TestCase):
|
|||
mark_busy.execute(_loadbalancer_mock)
|
||||
mock_amp_health_repo_update.assert_called_once_with(
|
||||
'TEST', amphora_id=AMP_ID, busy=True)
|
||||
|
||||
@mock.patch('octavia.db.repositories.LoadBalancerRepository.update')
|
||||
def test_update_lb_server_group_in_db(self,
|
||||
mock_listner_repo_update,
|
||||
mock_generate_uuid,
|
||||
mock_LOG,
|
||||
mock_get_session,
|
||||
mock_loadbalancer_repo_update,
|
||||
mock_listener_repo_update,
|
||||
mock_amphora_repo_update,
|
||||
mock_amphora_repo_delete):
|
||||
|
||||
update_server_group_info = database_tasks.UpdateLBServerGroupInDB()
|
||||
update_server_group_info.execute(LB_ID, SERVER_GROUP_ID)
|
||||
|
||||
repo.LoadBalancerRepository.update.assert_called_once_with(
|
||||
'TEST',
|
||||
id=LB_ID,
|
||||
server_group_id=SERVER_GROUP_ID)
|
||||
|
||||
# Test the revert
|
||||
|
||||
mock_listener_repo_update.reset_mock()
|
||||
update_server_group_info.revert(LB_ID, SERVER_GROUP_ID)
|
||||
|
|
|
@ -469,7 +469,12 @@ class TestControllerWorker(base.TestCase):
|
|||
(base_taskflow.BaseTaskFlowEngine._taskflow_load.
|
||||
assert_called_once_with(_flow_mock,
|
||||
store={constants.LOADBALANCER:
|
||||
_load_balancer_mock}))
|
||||
_load_balancer_mock,
|
||||
constants.SERVER_GROUP_ID:
|
||||
_load_balancer_mock.server_group_id
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
_flow_mock.run.assert_called_once_with()
|
||||
|
||||
|
|
Loading…
Reference in New Issue