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.
|
# the OpenStack services.
|
||||||
# endpoint_type = publicURL
|
# endpoint_type = publicURL
|
||||||
|
|
||||||
|
# Flag to enable nova anti-affinity capabilities to place amphorae on
|
||||||
|
# different hosts
|
||||||
|
# enable_anti_affinity = False
|
||||||
|
|
||||||
[neutron]
|
[neutron]
|
||||||
# The name of the neutron service in the keystone catalog
|
# The name of the neutron service in the keystone catalog
|
||||||
# service_name =
|
# service_name =
|
||||||
|
|
|
@ -359,6 +359,9 @@ nova_opts = [
|
||||||
'communication with the OpenStack services.')),
|
'communication with the OpenStack services.')),
|
||||||
cfg.StrOpt('endpoint_type', default='publicURL',
|
cfg.StrOpt('endpoint_type', default='publicURL',
|
||||||
help=_('Endpoint interface in identity service to use')),
|
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 = [
|
neutron_opts = [
|
||||||
|
|
|
@ -139,6 +139,8 @@ LISTENER = 'listener'
|
||||||
LISTENERS = 'listeners'
|
LISTENERS = 'listeners'
|
||||||
LOADBALANCER = 'loadbalancer'
|
LOADBALANCER = 'loadbalancer'
|
||||||
LOADBALANCER_ID = 'loadbalancer_id'
|
LOADBALANCER_ID = 'loadbalancer_id'
|
||||||
|
SERVER_GROUP_ID = 'server_group_id'
|
||||||
|
ANTI_AFFINITY = 'anti-affinity'
|
||||||
MEMBER = 'member'
|
MEMBER = 'member'
|
||||||
MEMBER_ID = 'member_id'
|
MEMBER_ID = 'member_id'
|
||||||
COMPUTE_ID = 'compute_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_AMPHORA_FOR_LB_FLOW = 'octavia-create-amp-for-lb-flow'
|
||||||
CREATE_HEALTH_MONITOR_FLOW = 'octavia-create-health-monitor-flow'
|
CREATE_HEALTH_MONITOR_FLOW = 'octavia-create-health-monitor-flow'
|
||||||
CREATE_LISTENER_FLOW = 'octavia-create-listener_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_LOADBALANCER_FLOW = 'octavia-create-loadbalancer-flow'
|
||||||
CREATE_MEMBER_FLOW = 'octavia-create-member-flow'
|
CREATE_MEMBER_FLOW = 'octavia-create-member-flow'
|
||||||
CREATE_POOL_FLOW = 'octavia-create-pool-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'
|
GENERATE_SERVER_PEM_TASK = 'GenerateServerPEMTask'
|
||||||
|
|
||||||
|
|
||||||
# Task Names
|
# Task Names
|
||||||
RELOAD_LB_AFTER_AMP_ASSOC = 'reload-lb-after-amp-assoc'
|
RELOAD_LB_AFTER_AMP_ASSOC = 'reload-lb-after-amp-assoc'
|
||||||
RELOAD_LB_AFTER_PLUG_VIP = 'reload-lb-after-plug-vip'
|
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,
|
def __init__(self, id=None, project_id=None, name=None, description=None,
|
||||||
provisioning_status=None, operating_status=None, enabled=None,
|
provisioning_status=None, operating_status=None, enabled=None,
|
||||||
topology=None, vip=None, listeners=None, amphorae=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.id = id
|
||||||
self.project_id = project_id
|
self.project_id = project_id
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -324,6 +325,7 @@ class LoadBalancer(BaseDataModel):
|
||||||
self.listeners = listeners or []
|
self.listeners = listeners or []
|
||||||
self.amphorae = amphorae or []
|
self.amphorae = amphorae or []
|
||||||
self.pools = pools or []
|
self.pools = pools or []
|
||||||
|
self.server_group_id = server_group_id
|
||||||
|
|
||||||
|
|
||||||
class VRRPGroup(BaseDataModel):
|
class VRRPGroup(BaseDataModel):
|
||||||
|
|
|
@ -217,3 +217,11 @@ class InvalidRegex(OctaviaException):
|
||||||
|
|
||||||
class InvalidL7Rule(OctaviaException):
|
class InvalidL7Rule(OctaviaException):
|
||||||
message = _LE('Invalid L7 Rule: $(msg)s')
|
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
|
@abc.abstractmethod
|
||||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||||
key_name=None, sec_groups=None, network_ids=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.
|
"""Build a new amphora.
|
||||||
|
|
||||||
:param name: Optional name for 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
|
: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
|
metadata server this can be a file type object as well or
|
||||||
a string
|
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
|
:raises ComputeBuildException: if compute failed to build amphora
|
||||||
:returns: UUID of amphora
|
:returns: UUID of amphora
|
||||||
|
@ -71,3 +73,21 @@ class ComputeBase(object):
|
||||||
:returns: the amphora object
|
:returns: the amphora object
|
||||||
"""
|
"""
|
||||||
pass
|
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,
|
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||||
key_name=None, sec_groups=None, network_ids=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, "
|
LOG.debug("Compute %s no-op, build name %s, amphora_flavor %s, "
|
||||||
"image_id %s, key_name %s, sec_groups %s, network_ids %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,
|
self.__class__.__name__, name, amphora_flavor, image_id,
|
||||||
key_name, sec_groups, network_ids, config_drive_files,
|
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,
|
self.computeconfig[(name, amphora_flavor, image_id, key_name,
|
||||||
user_data)] = (
|
user_data)] = (
|
||||||
name, amphora_flavor,
|
name, amphora_flavor,
|
||||||
|
@ -66,6 +68,16 @@ class NoopManager(object):
|
||||||
lb_network_ip='192.0.2.1'
|
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):
|
class NoopComputeDriver(driver_base.ComputeBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -74,11 +86,13 @@ class NoopComputeDriver(driver_base.ComputeBase):
|
||||||
|
|
||||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||||
key_name=None, sec_groups=None, network_ids=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,
|
compute_id = self.driver.build(name, amphora_flavor, image_id,
|
||||||
key_name, sec_groups, network_ids,
|
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
|
return compute_id
|
||||||
|
|
||||||
def delete(self, compute_id):
|
def delete(self, compute_id):
|
||||||
|
@ -89,3 +103,9 @@ class NoopComputeDriver(driver_base.ComputeBase):
|
||||||
|
|
||||||
def get_amphora(self, compute_id):
|
def get_amphora(self, compute_id):
|
||||||
return self.driver.get_amphora(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,
|
region=CONF.nova.region_name,
|
||||||
endpoint_type=CONF.nova.endpoint_type)
|
endpoint_type=CONF.nova.endpoint_type)
|
||||||
self.manager = self._nova_client.servers
|
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,
|
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||||
key_name=None, sec_groups=None, network_ids=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.
|
'''Create a new virtual machine.
|
||||||
|
|
||||||
:param name: optional name for amphora
|
: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
|
: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
|
metadata server this can be a file type object as well or
|
||||||
a string
|
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
|
:raises ComputeBuildException: if nova failed to build virtual machine
|
||||||
:returns: UUID of amphora
|
:returns: UUID of amphora
|
||||||
|
@ -77,13 +81,17 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||||
if port_ids:
|
if port_ids:
|
||||||
nics.extend([{"port-id": port_id} for port_id in 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(
|
amphora = self.manager.create(
|
||||||
name=name, image=image_id, flavor=amphora_flavor,
|
name=name, image=image_id, flavor=amphora_flavor,
|
||||||
key_name=key_name, security_groups=sec_groups,
|
key_name=key_name, security_groups=sec_groups,
|
||||||
nics=nics,
|
nics=nics,
|
||||||
files=config_drive_files,
|
files=config_drive_files,
|
||||||
userdata=user_data,
|
userdata=user_data,
|
||||||
config_drive=True
|
config_drive=True,
|
||||||
|
scheduler_hints=server_group
|
||||||
)
|
)
|
||||||
|
|
||||||
return amphora.id
|
return amphora.id
|
||||||
|
@ -175,3 +183,36 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||||
lb_network_ip=lb_network_ip
|
lb_network_ip=lb_network_ip
|
||||||
)
|
)
|
||||||
return response
|
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(),
|
lb = self._lb_repo.get(db_apis.get_session(),
|
||||||
id=load_balancer_id)
|
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.
|
delete_lb_tf = self._taskflow_load(self._lb_flows.
|
||||||
get_delete_load_balancer_flow(),
|
get_delete_load_balancer_flow(),
|
||||||
store={constants.LOADBALANCER: lb})
|
store=store)
|
||||||
|
|
||||||
with tf_logging.DynamicLoggingListener(delete_lb_tf,
|
with tf_logging.DynamicLoggingListener(delete_lb_tf,
|
||||||
log=LOG):
|
log=LOG):
|
||||||
|
|
|
@ -26,6 +26,7 @@ from octavia.controller.worker.tasks import network_tasks
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.import_group('controller_worker', 'octavia.common.config')
|
CONF.import_group('controller_worker', 'octavia.common.config')
|
||||||
|
CONF.import_group('nova', 'octavia.common.config')
|
||||||
|
|
||||||
|
|
||||||
class AmphoraFlows(object):
|
class AmphoraFlows(object):
|
||||||
|
@ -111,11 +112,12 @@ class AmphoraFlows(object):
|
||||||
|
|
||||||
sf_name = prefix + '-' + constants.CREATE_AMP_FOR_LB_SUBFLOW
|
sf_name = prefix + '-' + constants.CREATE_AMP_FOR_LB_SUBFLOW
|
||||||
create_amp_for_lb_subflow = linear_flow.Flow(sf_name)
|
create_amp_for_lb_subflow = linear_flow.Flow(sf_name)
|
||||||
|
|
||||||
create_amp_for_lb_subflow.add(database_tasks.CreateAmphoraInDB(
|
create_amp_for_lb_subflow.add(database_tasks.CreateAmphoraInDB(
|
||||||
name=sf_name + '-' + constants.CREATE_AMPHORA_INDB,
|
name=sf_name + '-' + constants.CREATE_AMPHORA_INDB,
|
||||||
provides=constants.AMPHORA_ID))
|
provides=constants.AMPHORA_ID))
|
||||||
|
|
||||||
|
anti_affinity = CONF.nova.enable_anti_affinity
|
||||||
|
|
||||||
if self.REST_AMPHORA_DRIVER:
|
if self.REST_AMPHORA_DRIVER:
|
||||||
create_amp_for_lb_subflow.add(cert_task.GenerateServerPEMTask(
|
create_amp_for_lb_subflow.add(cert_task.GenerateServerPEMTask(
|
||||||
name=sf_name + '-' + constants.GENERATE_SERVER_PEM,
|
name=sf_name + '-' + constants.GENERATE_SERVER_PEM,
|
||||||
|
@ -126,15 +128,31 @@ class AmphoraFlows(object):
|
||||||
name=sf_name + '-' + constants.UPDATE_CERT_EXPIRATION,
|
name=sf_name + '-' + constants.UPDATE_CERT_EXPIRATION,
|
||||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM)))
|
requires=(constants.AMPHORA_ID, constants.SERVER_PEM)))
|
||||||
|
|
||||||
create_amp_for_lb_subflow.add(compute_tasks.CertComputeCreate(
|
if role in (constants.ROLE_BACKUP, constants.ROLE_MASTER
|
||||||
name=sf_name + '-' + constants.CERT_COMPUTE_CREATE,
|
) and anti_affinity:
|
||||||
requires=(constants.AMPHORA_ID, constants.SERVER_PEM),
|
create_amp_for_lb_subflow.add(compute_tasks.CertComputeCreate(
|
||||||
provides=constants.COMPUTE_ID))
|
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:
|
else:
|
||||||
create_amp_for_lb_subflow.add(compute_tasks.ComputeCreate(
|
|
||||||
name=sf_name + '-' + constants.COMPUTE_CREATE,
|
if role in (constants.ROLE_BACKUP, constants.ROLE_MASTER
|
||||||
requires=constants.AMPHORA_ID,
|
) and anti_affinity:
|
||||||
provides=constants.COMPUTE_ID))
|
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(
|
create_amp_for_lb_subflow.add(database_tasks.UpdateAmphoraComputeId(
|
||||||
name=sf_name + '-' + constants.UPDATE_AMPHORA_COMPUTEID,
|
name=sf_name + '-' + constants.UPDATE_AMPHORA_COMPUTEID,
|
||||||
|
|
|
@ -31,6 +31,7 @@ from octavia.i18n import _LE
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.import_group('controller_worker', 'octavia.common.config')
|
CONF.import_group('controller_worker', 'octavia.common.config')
|
||||||
|
CONF.import_group('nova', 'octavia.common.config')
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,18 +45,46 @@ class LoadBalancerFlows(object):
|
||||||
|
|
||||||
two spare amphorae.
|
two spare amphorae.
|
||||||
:raises InvalidTopology: Invalid topology specified
|
: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
|
f_name = constants.CREATE_LOADBALANCER_FLOW
|
||||||
lb_create_flow = unordered_flow.Flow(f_name)
|
lb_create_flow = unordered_flow.Flow(f_name)
|
||||||
|
|
||||||
if topology == constants.TOPOLOGY_ACTIVE_STANDBY:
|
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(
|
master_amp_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||||
prefix=constants.ROLE_MASTER, role=constants.ROLE_MASTER)
|
prefix=constants.ROLE_MASTER, role=constants.ROLE_MASTER)
|
||||||
|
|
||||||
backup_amp_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
backup_amp_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||||
prefix=constants.ROLE_BACKUP, role=constants.ROLE_BACKUP)
|
prefix=constants.ROLE_BACKUP, role=constants.ROLE_BACKUP)
|
||||||
|
|
||||||
lb_create_flow.add(master_amp_sf, backup_amp_sf)
|
lb_create_flow.add(master_amp_sf, backup_amp_sf)
|
||||||
|
|
||||||
elif topology == constants.TOPOLOGY_SINGLE:
|
elif topology == constants.TOPOLOGY_SINGLE:
|
||||||
amphora_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
amphora_sf = self.amp_flows.get_amphora_for_lb_subflow(
|
||||||
prefix=constants.ROLE_STANDALONE,
|
prefix=constants.ROLE_STANDALONE,
|
||||||
|
@ -66,7 +95,8 @@ class LoadBalancerFlows(object):
|
||||||
"balancer."), topology)
|
"balancer."), topology)
|
||||||
raise exceptions.InvalidTopology(topology=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):
|
def get_post_lb_amp_association_flow(self, prefix, topology):
|
||||||
"""Reload the loadbalancer and create networking subflows for
|
"""Reload the loadbalancer and create networking subflows for
|
||||||
|
@ -109,6 +139,8 @@ class LoadBalancerFlows(object):
|
||||||
:returns: The flow for deleting a load balancer
|
:returns: The flow for deleting a load balancer
|
||||||
"""
|
"""
|
||||||
delete_LB_flow = linear_flow.Flow(constants.DELETE_LOADBALANCER_FLOW)
|
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(
|
delete_LB_flow.add(database_tasks.MarkLBAmphoraeHealthBusy(
|
||||||
requires=constants.LOADBALANCER))
|
requires=constants.LOADBALANCER))
|
||||||
delete_LB_flow.add(controller_tasks.DeleteListenersOnLB(
|
delete_LB_flow.add(controller_tasks.DeleteListenersOnLB(
|
||||||
|
|
|
@ -48,7 +48,8 @@ class BaseComputeTask(task.Task):
|
||||||
class ComputeCreate(BaseComputeTask):
|
class ComputeCreate(BaseComputeTask):
|
||||||
"""Create the compute instance for a new amphora."""
|
"""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
|
"""Create an amphora
|
||||||
|
|
||||||
:returns: an amphora
|
:returns: an amphora
|
||||||
|
@ -82,7 +83,8 @@ class ComputeCreate(BaseComputeTask):
|
||||||
network_ids=[CONF.controller_worker.amp_network],
|
network_ids=[CONF.controller_worker.amp_network],
|
||||||
port_ids=[port.id for port in ports],
|
port_ids=[port.id for port in ports],
|
||||||
config_drive_files=config_drive_files,
|
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",
|
LOG.debug("Server created with id: %s for amphora id: %s",
|
||||||
compute_id, amphora_id)
|
compute_id, amphora_id)
|
||||||
|
@ -111,7 +113,8 @@ class ComputeCreate(BaseComputeTask):
|
||||||
|
|
||||||
|
|
||||||
class CertComputeCreate(ComputeCreate):
|
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
|
"""Create an amphora
|
||||||
|
|
||||||
:returns: an amphora
|
:returns: an amphora
|
||||||
|
@ -125,7 +128,8 @@ class CertComputeCreate(ComputeCreate):
|
||||||
'/etc/octavia/certs/server.pem': server_pem,
|
'/etc/octavia/certs/server.pem': server_pem,
|
||||||
'/etc/octavia/certs/client_ca.pem': ca}
|
'/etc/octavia/certs/client_ca.pem': ca}
|
||||||
return super(CertComputeCreate, self).execute(
|
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):
|
class DeleteAmphoraeOnLoadBalancer(BaseComputeTask):
|
||||||
|
@ -177,3 +181,39 @@ class ComputeWait(BaseComputeTask):
|
||||||
time.sleep(CONF.controller_worker.amp_active_wait_sec)
|
time.sleep(CONF.controller_worker.amp_active_wait_sec)
|
||||||
|
|
||||||
raise exceptions.ComputeWaitTimeoutException()
|
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)
|
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):
|
class MarkLBDeletedInDB(BaseDatabaseTask):
|
||||||
"""Mark the load balancer deleted in the DB.
|
"""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,
|
amphorae = orm.relationship("Amphora", uselist=True,
|
||||||
backref=orm.backref("load_balancer",
|
backref=orm.backref("load_balancer",
|
||||||
uselist=False))
|
uselist=False))
|
||||||
|
server_group_id = sa.Column(sa.String(36), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
class VRRPGroup(base_models.BASE):
|
class VRRPGroup(base_models.BASE):
|
||||||
|
|
|
@ -103,7 +103,8 @@ class ModelTestMixin(object):
|
||||||
'id': self.FAKE_UUID_1,
|
'id': self.FAKE_UUID_1,
|
||||||
'provisioning_status': constants.ACTIVE,
|
'provisioning_status': constants.ACTIVE,
|
||||||
'operating_status': constants.ONLINE,
|
'operating_status': constants.ONLINE,
|
||||||
'enabled': True}
|
'enabled': True,
|
||||||
|
'server_group_id': self.FAKE_UUID_1}
|
||||||
kwargs.update(overrides)
|
kwargs.update(overrides)
|
||||||
return self._insert(session, models.LoadBalancer, kwargs)
|
return self._insert(session, models.LoadBalancer, kwargs)
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
|
||||||
'operating_status': constants.OFFLINE,
|
'operating_status': constants.OFFLINE,
|
||||||
'topology': constants.TOPOLOGY_ACTIVE_STANDBY,
|
'topology': constants.TOPOLOGY_ACTIVE_STANDBY,
|
||||||
'vrrp_group': None,
|
'vrrp_group': None,
|
||||||
|
'server_group_id': uuidutils.generate_uuid(),
|
||||||
'project_id': uuidutils.generate_uuid()}
|
'project_id': uuidutils.generate_uuid()}
|
||||||
vip = {'ip_address': '10.0.0.1',
|
vip = {'ip_address': '10.0.0.1',
|
||||||
'port_id': uuidutils.generate_uuid(),
|
'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,
|
self.session, id=self.FAKE_UUID_1, project_id=self.FAKE_UUID_2,
|
||||||
name="lb_name", description="lb_description",
|
name="lb_name", description="lb_description",
|
||||||
provisioning_status=constants.ACTIVE,
|
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):
|
def create_listener(self, listener_id, port, default_pool_id=None):
|
||||||
listener = self.listener_repo.create(
|
listener = self.listener_repo.create(
|
||||||
|
|
|
@ -36,15 +36,20 @@ class TestNoopComputeDriver(base.TestCase):
|
||||||
self.confdrivefiles = "config_driver_files"
|
self.confdrivefiles = "config_driver_files"
|
||||||
self.user_data = "user_data"
|
self.user_data = "user_data"
|
||||||
self.amphora_id = self.FAKE_UUID_1
|
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):
|
def build(self):
|
||||||
self.driver.build(self.name, self.amphora_flavor, self.image_id,
|
self.driver.build(self.name, self.amphora_flavor, self.image_id,
|
||||||
self.key_name, self.sec_groups, self.network_ids,
|
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.assertEqual((self.name, self.amphora_flavor, self.image_id,
|
||||||
self.key_name, self.sec_groups, self.network_ids,
|
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.driver.driver.computeconfig[(self.name,
|
||||||
self.amphora_flavor,
|
self.amphora_flavor,
|
||||||
self.image_id,
|
self.image_id,
|
||||||
|
@ -52,7 +57,9 @@ class TestNoopComputeDriver(base.TestCase):
|
||||||
self.sec_groups,
|
self.sec_groups,
|
||||||
self.network_ids,
|
self.network_ids,
|
||||||
self.confdrivefiles,
|
self.confdrivefiles,
|
||||||
self.user_data)])
|
self.user_data,
|
||||||
|
self.server_group_id
|
||||||
|
)])
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
self.driver.delete(self.amphora_id)
|
self.driver.delete(self.amphora_id)
|
||||||
|
@ -65,3 +72,10 @@ class TestNoopComputeDriver(base.TestCase):
|
||||||
|
|
||||||
def get_amphora(self):
|
def get_amphora(self):
|
||||||
self.driver.get_amphora(self.amphora_id)
|
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.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
from novaclient import exceptions as nova_exceptions
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
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 = [mock.MagicMock()]
|
||||||
self.interface_list.fixed_ips[0] = {'ip_address': '10.0.0.1'}
|
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 = nova_common.VirtualMachineManager()
|
||||||
self.manager.manager = mock.MagicMock()
|
self.manager.manager = mock.MagicMock()
|
||||||
|
self.manager.server_groups = mock.MagicMock()
|
||||||
self.manager._nova_client = mock.MagicMock()
|
self.manager._nova_client = mock.MagicMock()
|
||||||
|
|
||||||
self.nova_response.interface_list.side_effect = [[self.interface_list]]
|
self.nova_response.interface_list.side_effect = [[self.interface_list]]
|
||||||
self.manager.manager.get.return_value = self.nova_response
|
self.manager.manager.get.return_value = self.nova_response
|
||||||
self.manager.manager.create.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_response.addresses = {self.net_name: [{'addr': '10.0.0.1'}]}
|
||||||
|
|
||||||
self.nova_network = mock.Mock()
|
self.nova_network = mock.Mock()
|
||||||
self.nova_network.label = self.net_name
|
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()
|
super(TestNovaClient, self).setUp()
|
||||||
|
|
||||||
def test_build(self):
|
def test_build(self):
|
||||||
|
@ -85,7 +101,8 @@ class TestNovaClient(base.TestCase):
|
||||||
security_groups=1,
|
security_groups=1,
|
||||||
files='Files Blah',
|
files='Files Blah',
|
||||||
userdata='Blah',
|
userdata='Blah',
|
||||||
config_drive=True)
|
config_drive=True,
|
||||||
|
scheduler_hints=None)
|
||||||
|
|
||||||
def test_bad_build(self):
|
def test_bad_build(self):
|
||||||
self.manager.manager.create.side_effect = Exception
|
self.manager.manager.create.side_effect = Exception
|
||||||
|
@ -144,3 +161,43 @@ class TestNovaClient(base.TestCase):
|
||||||
self.assertEqual(self.amphora, amphora)
|
self.assertEqual(self.amphora, amphora)
|
||||||
self.assertTrue(self.nova_response.interface_list.called)
|
self.assertTrue(self.nova_response.interface_list.called)
|
||||||
self.manager._nova_client.networks.get.called_with(self.net_name)
|
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.context = {}
|
||||||
self.resource_updates = {}
|
self.resource_updates = {}
|
||||||
self.resource_id = 1234
|
self.resource_id = 1234
|
||||||
|
self.server_group_id = 3456
|
||||||
|
|
||||||
def test_create_load_balancer(self):
|
def test_create_load_balancer(self):
|
||||||
self.ep.create_load_balancer(self.context, self.resource_id)
|
self.ep.create_load_balancer(self.context, self.resource_id)
|
||||||
|
|
|
@ -30,6 +30,8 @@ class TestAmphoraFlows(base.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||||
group='controller_worker')
|
group='controller_worker')
|
||||||
|
cfg.CONF.set_override('enable_anti_affinity', False,
|
||||||
|
group='nova')
|
||||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||||
conf = oslo_fixture.Config(cfg.CONF)
|
conf = oslo_fixture.Config(cfg.CONF)
|
||||||
conf.config(group="keystone_authtoken", auth_version=AUTH_VERSION)
|
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):
|
def test_get_cert_create_amphora_for_lb_flow(self):
|
||||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||||
group='controller_worker')
|
group='controller_worker')
|
||||||
|
|
||||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||||
|
|
||||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
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):
|
def test_get_cert_master_create_amphora_for_lb_flow(self):
|
||||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||||
group='controller_worker')
|
group='controller_worker')
|
||||||
|
|
||||||
self.AmpFlow = amphora_flows.AmphoraFlows()
|
self.AmpFlow = amphora_flows.AmphoraFlows()
|
||||||
|
|
||||||
amp_flow = self.AmpFlow._get_create_amp_for_lb_subflow(
|
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(5, len(amp_flow.provides))
|
||||||
self.assertEqual(1, len(amp_flow.requires))
|
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):
|
def test_get_cert_backup_create_amphora_for_lb_flow(self):
|
||||||
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
cfg.CONF.set_override('amphora_driver', 'amphora_haproxy_rest_driver',
|
||||||
group='controller_worker')
|
group='controller_worker')
|
||||||
|
@ -170,6 +196,27 @@ class TestAmphoraFlows(base.TestCase):
|
||||||
self.assertEqual(5, len(amp_flow.provides))
|
self.assertEqual(5, len(amp_flow.provides))
|
||||||
self.assertEqual(1, len(amp_flow.requires))
|
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):
|
def test_get_delete_amphora_flow(self):
|
||||||
|
|
||||||
amp_flow = self.AmpFlow.get_delete_amphora_flow()
|
amp_flow = self.AmpFlow.get_delete_amphora_flow()
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# 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 linear_flow as flow
|
||||||
from taskflow.patterns import unordered_flow
|
|
||||||
|
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
from octavia.common import exceptions
|
from octavia.common import exceptions
|
||||||
|
@ -26,13 +26,14 @@ class TestLoadBalancerFlows(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.LBFlow = load_balancer_flows.LoadBalancerFlows()
|
self.LBFlow = load_balancer_flows.LoadBalancerFlows()
|
||||||
|
conf = oslo_fixture.Config(cfg.CONF)
|
||||||
|
conf.config(group="nova", enable_anti_affinity=False)
|
||||||
super(TestLoadBalancerFlows, self).setUp()
|
super(TestLoadBalancerFlows, self).setUp()
|
||||||
|
|
||||||
def test_get_create_load_balancer_flow(self):
|
def test_get_create_load_balancer_flow(self):
|
||||||
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
||||||
constants.TOPOLOGY_SINGLE)
|
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.LOADBALANCER_ID, amp_flow.requires)
|
||||||
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
||||||
self.assertIn(constants.AMPHORA_ID, 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):
|
def test_get_create_active_standby_load_balancer_flow(self):
|
||||||
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
amp_flow = self.LBFlow.get_create_load_balancer_flow(
|
||||||
constants.TOPOLOGY_ACTIVE_STANDBY)
|
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.LOADBALANCER_ID, amp_flow.requires)
|
||||||
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
self.assertIn(constants.AMPHORA, amp_flow.provides)
|
||||||
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
self.assertIn(constants.AMPHORA_ID, amp_flow.provides)
|
||||||
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
self.assertIn(constants.COMPUTE_ID, amp_flow.provides)
|
||||||
self.assertIn(constants.COMPUTE_OBJ, 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):
|
def test_get_create_bogus_topology_load_balancer_flow(self):
|
||||||
self.assertRaises(exceptions.InvalidTopology,
|
self.assertRaises(exceptions.InvalidTopology,
|
||||||
self.LBFlow.get_create_load_balancer_flow,
|
self.LBFlow.get_create_load_balancer_flow,
|
||||||
|
@ -61,9 +76,10 @@ class TestLoadBalancerFlows(base.TestCase):
|
||||||
self.assertIsInstance(lb_flow, flow.Flow)
|
self.assertIsInstance(lb_flow, flow.Flow)
|
||||||
|
|
||||||
self.assertIn(constants.LOADBALANCER, lb_flow.requires)
|
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(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):
|
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
|
from oslo_utils import uuidutils
|
||||||
import six.moves.builtins as builtins
|
import six.moves.builtins as builtins
|
||||||
|
|
||||||
|
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
from octavia.common import exceptions
|
from octavia.common import exceptions
|
||||||
from octavia.controller.worker.tasks import compute_tasks
|
from octavia.controller.worker.tasks import compute_tasks
|
||||||
|
@ -35,6 +36,7 @@ COMPUTE_ID = uuidutils.generate_uuid()
|
||||||
LB_NET_IP = '192.0.2.1'
|
LB_NET_IP = '192.0.2.1'
|
||||||
PORT_ID = uuidutils.generate_uuid()
|
PORT_ID = uuidutils.generate_uuid()
|
||||||
AUTH_VERSION = '2'
|
AUTH_VERSION = '2'
|
||||||
|
SERVER_GRPOUP_ID = uuidutils.generate_uuid()
|
||||||
|
|
||||||
|
|
||||||
class TestException(Exception):
|
class TestException(Exception):
|
||||||
|
@ -85,7 +87,8 @@ class TestComputeTasks(base.TestCase):
|
||||||
|
|
||||||
mock_driver.build.return_value = COMPUTE_ID
|
mock_driver.build.return_value = COMPUTE_ID
|
||||||
# Test execute()
|
# 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
|
# Validate that the build method was called properly
|
||||||
mock_driver.build.assert_called_once_with(
|
mock_driver.build.assert_called_once_with(
|
||||||
|
@ -98,7 +101,8 @@ class TestComputeTasks(base.TestCase):
|
||||||
port_ids=[PORT_ID],
|
port_ids=[PORT_ID],
|
||||||
config_drive_files={'/etc/octavia/'
|
config_drive_files={'/etc/octavia/'
|
||||||
'amphora-agent.conf': 'test_conf'},
|
'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
|
# Make sure it returns the expected compute_id
|
||||||
assert(compute_id == COMPUTE_ID)
|
assert(compute_id == COMPUTE_ID)
|
||||||
|
@ -155,7 +159,8 @@ class TestComputeTasks(base.TestCase):
|
||||||
network_ids=[AMP_NET],
|
network_ids=[AMP_NET],
|
||||||
port_ids=[PORT_ID],
|
port_ids=[PORT_ID],
|
||||||
config_drive_files=None,
|
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
|
# Make sure it returns the expected compute_id
|
||||||
assert(compute_id == 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)
|
conf.config(group="controller_worker", amp_ssh_access_allowed=False)
|
||||||
|
|
||||||
# Test execute()
|
# 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
|
# Validate that the build method was called properly
|
||||||
mock_driver.build.assert_called_once_with(
|
mock_driver.build.assert_called_once_with(
|
||||||
|
@ -212,7 +218,8 @@ class TestComputeTasks(base.TestCase):
|
||||||
port_ids=[PORT_ID],
|
port_ids=[PORT_ID],
|
||||||
config_drive_files={'/etc/octavia/'
|
config_drive_files={'/etc/octavia/'
|
||||||
'amphora-agent.conf': 'test_conf'},
|
'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
|
# Make sure it returns the expected compute_id
|
||||||
self.assertEqual(COMPUTE_ID, compute_id)
|
self.assertEqual(COMPUTE_ID, compute_id)
|
||||||
|
@ -252,8 +259,9 @@ class TestComputeTasks(base.TestCase):
|
||||||
m = mock.mock_open(read_data='test')
|
m = mock.mock_open(read_data='test')
|
||||||
with mock.patch.object(builtins, 'open', m, create=True):
|
with mock.patch.object(builtins, 'open', m, create=True):
|
||||||
# Test execute()
|
# Test execute()
|
||||||
compute_id = createcompute.execute(_amphora_mock.id,
|
compute_id = createcompute.execute(_amphora_mock.id, 'test_cert',
|
||||||
'test_cert')
|
server_group_id=SERVER_GRPOUP_ID
|
||||||
|
)
|
||||||
|
|
||||||
# Validate that the build method was called properly
|
# Validate that the build method was called properly
|
||||||
mock_driver.build.assert_called_once_with(
|
mock_driver.build.assert_called_once_with(
|
||||||
|
@ -268,7 +276,8 @@ class TestComputeTasks(base.TestCase):
|
||||||
config_drive_files={
|
config_drive_files={
|
||||||
'/etc/octavia/certs/server.pem': 'test_cert',
|
'/etc/octavia/certs/server.pem': 'test_cert',
|
||||||
'/etc/octavia/certs/client_ca.pem': 'test',
|
'/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
|
# Make sure it returns the expected compute_id
|
||||||
assert(compute_id == COMPUTE_ID)
|
assert(compute_id == COMPUTE_ID)
|
||||||
|
@ -355,3 +364,44 @@ class TestComputeTasks(base.TestCase):
|
||||||
delete_compute.execute(_amphora_mock)
|
delete_compute.execute(_amphora_mock)
|
||||||
|
|
||||||
mock_driver.delete.assert_called_once_with(COMPUTE_ID)
|
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()
|
AMP_ID = uuidutils.generate_uuid()
|
||||||
COMPUTE_ID = uuidutils.generate_uuid()
|
COMPUTE_ID = uuidutils.generate_uuid()
|
||||||
LB_ID = uuidutils.generate_uuid()
|
LB_ID = uuidutils.generate_uuid()
|
||||||
|
SERVER_GROUP_ID = uuidutils.generate_uuid()
|
||||||
LB_NET_IP = '192.0.2.2'
|
LB_NET_IP = '192.0.2.2'
|
||||||
LISTENER_ID = uuidutils.generate_uuid()
|
LISTENER_ID = uuidutils.generate_uuid()
|
||||||
POOL_ID = uuidutils.generate_uuid()
|
POOL_ID = uuidutils.generate_uuid()
|
||||||
|
@ -1348,3 +1349,27 @@ class TestDatabaseTasks(base.TestCase):
|
||||||
mark_busy.execute(_loadbalancer_mock)
|
mark_busy.execute(_loadbalancer_mock)
|
||||||
mock_amp_health_repo_update.assert_called_once_with(
|
mock_amp_health_repo_update.assert_called_once_with(
|
||||||
'TEST', amphora_id=AMP_ID, busy=True)
|
'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.
|
(base_taskflow.BaseTaskFlowEngine._taskflow_load.
|
||||||
assert_called_once_with(_flow_mock,
|
assert_called_once_with(_flow_mock,
|
||||||
store={constants.LOADBALANCER:
|
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()
|
_flow_mock.run.assert_called_once_with()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue