예제 #1
0
class L7PolicyBuilder(object):
    """Class supports CRUD for L7 policies and rules

    Handles both L7 policy and L7 rules for these events:
      - create l7 policy
      - delete l7 policy
    """
    def __init__(self, event, f5_l7policy):
        self.event = event
        self.f5_l7policy = f5_l7policy
        self.helper = BigIPResourceHelper(ResourceType.l7policy)

        if event == 'DELETE_L7POLICY':
            # both rules and policies handled by same method
            self.execute = self.delete
        else:
            # create and update event for both rules and polices
            self.execute = self.create

    def create(self, bigip):
        LOG.debug("L7PolicyBuilder: create")
        if self.helper.exists(bigip,
                              name=self.f5_l7policy['name'],
                              partition=self.f5_l7policy['partition']):
            self.helper.update(bigip, self.f5_l7policy)
        else:
            self.helper.create(bigip, self.f5_l7policy)

    def delete(self, bigip):
        LOG.debug("L7PolicyBuilder: delete")
        self.helper.delete(
            bigip, self.f5_l7policy['name'], self.f5_l7policy['partition'])
예제 #2
0
class PoolServiceBuilder(object):
    """Create LBaaS v2 pools and related objects on BIG-IP®s.

    Handles requests to create, update, delete LBaaS v2 pools,
    health monitors, and members on one or more BIG-IP® systems.
    """

    def __init__(self, service_adapter):
        self.service_adapter = service_adapter
        self.http_mon_helper = BigIPResourceHelper(ResourceType.http_monitor)
        self.https_mon_helper = BigIPResourceHelper(ResourceType.https_monitor)
        self.tcp_mon_helper = BigIPResourceHelper(ResourceType.tcp_monitor)
        self.ping_mon_helper = BigIPResourceHelper(ResourceType.ping_monitor)
        self.pool_helper = BigIPResourceHelper(ResourceType.pool)
        self.node_helper = BigIPResourceHelper(ResourceType.node)

    def create_pool(self, service, bigips):
        """Create a pool on set of BIG-IP®s.

        Creates a BIG-IP® pool to represent an LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.create(bigip, pool)

    def delete_pool(self, service, bigips):
        """Delete a pool on set of BIG-IP®s.

        Deletes a BIG-IP® pool defined by LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to delete pool.
        """
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            self.pool_helper.delete(bigip,
                                    name=pool["name"],
                                    partition=pool["partition"])

    def update_pool(self, service, bigips):
        """Update BIG-IP® pool.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.update(bigip, pool)

    def create_healthmonitor(self, service, bigips):
        # create member
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.create(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    def delete_healthmonitor(self, service, bigips):
        # delete health monitor
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        # update pool
        pool = self.service_adapter.get_pool(service)
        pool["monitor"] = ""

        for bigip in bigips:
            # need to first remove monitor reference from pool
            self.pool_helper.update(bigip, pool)

            # after updating pool, delete monitor
            hm_helper.delete(bigip,
                             name=hm["name"],
                             partition=hm["partition"])

    def update_healthmonitor(self, service, bigips):
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        for bigip in bigips:
            hm_helper.update(bigip, hm)

    # Note: can't use BigIPResourceHelper class because members
    # are created within pool objects. Following member methods
    # use the F5® SDK directly.
    def create_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        for bigip in bigips:
            part = pool["partition"]
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)
            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)

            if not member_exists:
                m.create(**member)

    def delete_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)

            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)
            if member_exists:
                m = m.load(name=urllib.quote(member["name"]),
                           partition=part)

                m.delete()
                node = self.service_adapter.get_member_node(service)
                self.node_helper.delete(bigip,
                                        name=urllib.quote(node["name"]),
                                        partition=node["partition"])

    def update_member(self, service, bigips):
        # TODO(jl) handle state -- SDK enforces at least state=None

        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]),
                           partition=part)
                m.modify(**member)

    def _get_monitor_helper(self, service):
        monitor_type = self.service_adapter.get_monitor_type(service)
        if monitor_type == "HTTPS":
            hm = self.https_mon_helper
        elif monitor_type == "TCP":
            hm = self.tcp_mon_helper
        elif monitor_type == "PING":
            hm = self.ping_mon_helper
        else:
            hm = self.http_mon_helper
        return hm
class PoolServiceBuilder(object):
    """Create LBaaS v2 pools and related objects on BIG-IPs.

    Handles requests to create, update, delete LBaaS v2 pools,
    health monitors, and members on one or more BIG-IP systems.
    """
    def __init__(self, service_adapter):
        self.service_adapter = service_adapter
        self.http_mon_helper = BigIPResourceHelper(ResourceType.http_monitor)
        self.https_mon_helper = BigIPResourceHelper(ResourceType.https_monitor)
        self.tcp_mon_helper = BigIPResourceHelper(ResourceType.tcp_monitor)
        self.ping_mon_helper = BigIPResourceHelper(ResourceType.ping_monitor)
        self.pool_helper = BigIPResourceHelper(ResourceType.pool)
        self.node_helper = BigIPResourceHelper(ResourceType.node)

    def create_pool(self, service, bigips):
        """Create a pool on set of BIG-IPs.

        Creates a BIG-IP pool to represent an LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.create(bigip, pool)

    def delete_pool(self, service, bigips):
        """Delete a pool on set of BIG-IPs.

        Deletes a BIG-IP pool defined by LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to delete pool.
        """
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            self.pool_helper.delete(bigip,
                                    name=pool["name"],
                                    partition=pool["partition"])

    def update_pool(self, service, bigips):
        """Update BIG-IP pool.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.update(bigip, pool)

    def create_healthmonitor(self, service, bigips):
        # create member
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.create(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    def delete_healthmonitor(self, service, bigips):
        # delete health monitor
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        # update pool
        pool = self.service_adapter.get_pool(service)
        pool["monitor"] = ""

        for bigip in bigips:
            # need to first remove monitor reference from pool
            self.pool_helper.update(bigip, pool)

            # after updating pool, delete monitor
            hm_helper.delete(bigip, name=hm["name"], partition=hm["partition"])

    def update_healthmonitor(self, service, bigips):
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.update(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    # Note: can't use BigIPResourceHelper class because members
    # are created within pool objects. Following member methods
    # use the F5 SDK directly.
    def create_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        for bigip in bigips:
            part = pool["partition"]
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)
            m = p.members_s.members
            m.create(**member)

    def delete_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)

            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)
            if member_exists:
                m = m.load(name=urllib.quote(member["name"]), partition=part)

                m.delete()
                try:
                    node = self.service_adapter.get_member_node(service)
                    self.node_helper.delete(bigip,
                                            name=urllib.quote(node["name"]),
                                            partition=node["partition"])
                except HTTPError as err:
                    # Possilbe error if node is shared with another member.
                    # If so, ignore the error.
                    if err.response.status_code == 400:
                        LOG.debug(err.message)
                    else:
                        raise

    def update_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)

        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]), partition=part)
                member.pop("address", None)
                m.modify(**member)

    def delete_orphaned_members(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        srv_members = service['members']
        part = pool['partition']
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool['name'], partition=part)
            deployed_members = p.members_s.get_collection()
            for dm in deployed_members:
                orphaned = True
                for sm in srv_members:
                    svc = {
                        "loadbalancer": service["loadbalancer"],
                        "pool": service["pool"],
                        "member": sm
                    }
                    member = self.service_adapter.get_member(svc)
                    if member['name'] == dm.name:
                        orphaned = False
                if orphaned:
                    node_name = dm.address
                    dm.delete()
                    try:
                        self.node_helper.delete(bigip,
                                                name=urllib.quote(node_name),
                                                partition=part)
                    except HTTPError as err:
                        # Possilbe error if node is shared with another member.
                        # If so, ignore the error.
                        if err.response.status_code == 400:
                            LOG.debug(err.message)
                        else:
                            raise

    def _get_monitor_helper(self, service):
        monitor_type = self.service_adapter.get_monitor_type(service)
        if monitor_type == "HTTPS":
            hm = self.https_mon_helper
        elif monitor_type == "TCP":
            hm = self.tcp_mon_helper
        elif monitor_type == "PING":
            hm = self.ping_mon_helper
        else:
            hm = self.http_mon_helper
        return hm

    def get_member_status(self, service, bigip, status_keys):
        """Return status values for a single pool.

        Status keys to collect are defined as an array of strings in input
        status_keys.

        :param service: Has pool and member name/partition
        :param bigip: BIG-IP to get member status from.
        :param status_keys: Array of strings that define which status keys to
        collect.
        :return: A dict with key/value pairs for each status defined in
        input status_keys.
        """
        member_status = {}
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        try:
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]), partition=part)
                member_status = self.pool_helper.collect_stats(
                    m, stat_keys=status_keys)
            else:
                LOG.error(
                    "Unable to get member status. "
                    "Member %s does not exist.", member["name"])

        except Exception as e:
            # log error but continue on
            LOG.error("Error getting member status: %s", e.message)

        return member_status
예제 #4
0
class L7PolicyService(object):
    """Handles requests to create, update, delete L7 policies on BIG-IPs."""
    def __init__(self, conf):
        self.conf = conf
        self.policy_helper = BigIPResourceHelper(ResourceType.l7policy)
        self.rule_helper = BigIPResourceHelper(ResourceType.rule)

    def create_l7policy(self, f5_l7policy, bigips):
        LOG.debug("L7PolicyService: create_l7policy")

        error = None
        for bigip in bigips:
            try:
                self.policy_helper.create(bigip, f5_l7policy)
                error = None
            except HTTPError as err:
                status_code = err.response.status_code
                if status_code == 409:
                    LOG.debug("L7 policy already exists...updating")
                    try:
                        self.policy_helper.update(bigip, f5_l7policy)
                    except Exception as err:
                        error = f5_ex.L7PolicyUpdateException(err.message)
                else:
                    error = f5_ex.L7PolicyCreationException(err.message)
            except Exception as err:
                error = f5_ex.L7PolicyCreationException(err.message)

            if error:
                LOG.error("L7 policy creation error: %s" % error.message)

        return error

    def delete_l7policy(self, f5_l7policy, bigips):
        LOG.debug("L7PolicyService:delete_l7policy")

        error = False
        for bigip in bigips:
            try:
                self.policy_helper.delete(bigip, f5_l7policy['name'],
                                          f5_l7policy['partition'])
            except HTTPError as err:
                status_code = err.response.status_code
                if status_code == 404:
                    LOG.warn("Deleting L7 policy failed...not found: %s",
                             err.message)
                elif status_code == 400:
                    LOG.debug(
                        "Deleting L7 policy failed...unknown "
                        "client error: %s", err.message)
                    error = f5_ex.L7PolicyDeleteException(err.message)
                else:
                    error = f5_ex.L7PolicyDeleteException(err.message)
            except Exception as err:
                LOG.exception(err)
                error = f5_ex.L7PolicyDeleteException(err.message)

            if error:
                LOG.error("L7 Policy deletion error: %s", error.message)

        return error

    def build_policy(self, l7policy, lbaas_service):
        # build data structure for service adapter input
        LOG.debug("L7PolicyService: service")
        import pprint
        # LOG.debug(pprint.pformat(lbaas_service.service_object, indent=4))
        LOG.debug("L7PolicyService: l7policy")
        # LOG.debug(pprint.pformat(l7policy, indent=4))

        l7policy_adapter = L7PolicyServiceAdapter(self.conf)

        os_policies = {
            'l7rules': [],
            'l7policies': [],
            'f5_policy': {},
            'iRules': []
        }

        # get all policies and rules for listener referenced by this policy
        listener = lbaas_service.get_listener(l7policy['listener_id'])
        for policy_id in listener['l7_policies']:
            policy = lbaas_service.get_l7policy(policy_id['id'])
            if policy:
                os_policies['l7policies'].append(policy)
                for rule in policy['rules']:
                    l7rule = lbaas_service.get_l7rule(rule['id'])
                    if l7rule:
                        os_policies['l7rules'].append(l7rule)

        if os_policies['l7policies']:
            os_policies['f5_policy'] = l7policy_adapter.translate(os_policies)
            if getattr(l7policy_adapter, 'iRules', None):
                os_policies['iRules'] = l7policy_adapter.iRules

        LOG.debug(pprint.pformat(os_policies, indent=2))
        return os_policies

    def create_irule(self, irules, bigips):
        LOG.debug("L7PolicyService: create_iRule")

        error = None
        for bigip in bigips:
            for rule in irules:
                try:
                    self.rule_helper.create(bigip, rule)
                except HTTPError as err:
                    status_code = err.response.status_code
                    if status_code == 409:
                        LOG.debug(
                            "L7 rule (REGEX irule) already exists...updating")
                        try:
                            self.rule_helper.update(bigip, rule)
                        except Exception as err:
                            error = f5_ex.L7PolicyUpdateException(err.message)
                    else:
                        error = f5_ex.L7PolicyCreationException(err.message)
                except Exception as err:
                    error = f5_ex.L7PolicyCreationException(err.message)

                if error:
                    LOG.error("L7 rule (REGEX irule) creation error: %s" %
                              error.message)

        return error

    def delete_irule(self, delete_irules, bigips):
        LOG.debug("L7PolicyService:delete_iRule")

        error = False
        for bigip in bigips:
            for rule in delete_irules:
                try:
                    self.rule_helper.delete(bigip,
                                            name=rule.get('name'),
                                            partition=rule.get('partition'))
                except HTTPError as err:
                    status_code = err.response.status_code
                    if status_code == 404:
                        LOG.warn(
                            "Deleting L7 policy (iRule) " +
                            "failed...not found: %s", err.message)
                    elif status_code == 400:
                        LOG.debug(
                            "Deleting L7 policy (iRule) failed...unknown "
                            "client error: %s", err.message)
                        error = f5_ex.L7PolicyDeleteException(err.message)
                    else:
                        error = f5_ex.L7PolicyDeleteException(err.message)
                except Exception as err:
                    LOG.exception(err)
                    error = f5_ex.L7PolicyDeleteException(err.message)

                if error:
                    LOG.error("L7 Policy (iRule) deletion error: %s",
                              error.message)

        return error
예제 #5
0
class PoolServiceBuilder(object):
    """Create LBaaS v2 pools and related objects on BIG-IP®s.

    Handles requests to create, update, delete LBaaS v2 pools,
    health monitors, and members on one or more BIG-IP® systems.
    """
    def __init__(self, service_adapter):
        self.service_adapter = service_adapter
        self.http_mon_helper = BigIPResourceHelper(ResourceType.http_monitor)
        self.https_mon_helper = BigIPResourceHelper(ResourceType.https_monitor)
        self.tcp_mon_helper = BigIPResourceHelper(ResourceType.tcp_monitor)
        self.ping_mon_helper = BigIPResourceHelper(ResourceType.ping_monitor)
        self.pool_helper = BigIPResourceHelper(ResourceType.pool)
        self.node_helper = BigIPResourceHelper(ResourceType.node)

    def create_pool(self, service, bigips):
        """Create a pool on set of BIG-IP®s.

        Creates a BIG-IP® pool to represent an LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.create(bigip, pool)

    def delete_pool(self, service, bigips):
        """Delete a pool on set of BIG-IP®s.

        Deletes a BIG-IP® pool defined by LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to delete pool.
        """
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            self.pool_helper.delete(bigip,
                                    name=pool["name"],
                                    partition=pool["partition"])

    def update_pool(self, service, bigips):
        """Update BIG-IP® pool.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.update(bigip, pool)

    def create_healthmonitor(self, service, bigips):
        # create member
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.create(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    def delete_healthmonitor(self, service, bigips):
        # delete health monitor
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        # update pool
        pool = self.service_adapter.get_pool(service)
        pool["monitor"] = ""

        for bigip in bigips:
            # need to first remove monitor reference from pool
            self.pool_helper.update(bigip, pool)

            # after updating pool, delete monitor
            hm_helper.delete(bigip, name=hm["name"], partition=hm["partition"])

    def update_healthmonitor(self, service, bigips):
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        for bigip in bigips:
            hm_helper.update(bigip, hm)

    # Note: can't use BigIPResourceHelper class because members
    # are created within pool objects. Following member methods
    # use the F5® SDK directly.
    def create_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        for bigip in bigips:
            part = pool["partition"]
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)
            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)

            if not member_exists:
                m.create(**member)

    def delete_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)

            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)
            if member_exists:
                m = m.load(name=urllib.quote(member["name"]), partition=part)

                m.delete()
                node = self.service_adapter.get_member_node(service)
                self.node_helper.delete(bigip,
                                        name=urllib.quote(node["name"]),
                                        partition=node["partition"])

    def update_member(self, service, bigips):
        # TODO(jl) handle state -- SDK enforces at least state=None

        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool["name"], partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]), partition=part)
                m.modify(**member)

    def _get_monitor_helper(self, service):
        monitor_type = self.service_adapter.get_monitor_type(service)
        if monitor_type == "HTTPS":
            hm = self.https_mon_helper
        elif monitor_type == "TCP":
            hm = self.tcp_mon_helper
        elif monitor_type == "PING":
            hm = self.ping_mon_helper
        else:
            hm = self.http_mon_helper
        return hm
예제 #6
0
class PoolServiceBuilder(object):
    """Create LBaaS v2 pools and related objects on BIG-IPs.

    Handles requests to create, update, delete LBaaS v2 pools,
    health monitors, and members on one or more BIG-IP systems.
    """

    def __init__(self, service_adapter):
        self.service_adapter = service_adapter
        self.http_mon_helper = BigIPResourceHelper(ResourceType.http_monitor)
        self.https_mon_helper = BigIPResourceHelper(ResourceType.https_monitor)
        self.tcp_mon_helper = BigIPResourceHelper(ResourceType.tcp_monitor)
        self.ping_mon_helper = BigIPResourceHelper(ResourceType.ping_monitor)
        self.pool_helper = BigIPResourceHelper(ResourceType.pool)
        self.node_helper = BigIPResourceHelper(ResourceType.node)

    def create_pool(self, service, bigips):
        """Create a pool on set of BIG-IPs.

        Creates a BIG-IP pool to represent an LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.create(bigip, pool)

    def delete_pool(self, service, bigips):
        """Delete a pool on set of BIG-IPs.

        Deletes a BIG-IP pool defined by LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to delete pool.
        """
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            self.pool_helper.delete(bigip,
                                    name=pool["name"],
                                    partition=pool["partition"])

    def update_pool(self, service, bigips):
        """Update BIG-IP pool.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create pool.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.update(bigip, pool)

    def create_healthmonitor(self, service, bigips):
        # create member
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.create(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    def delete_healthmonitor(self, service, bigips):
        # delete health monitor
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        # update pool
        pool = self.service_adapter.get_pool(service)
        pool["monitor"] = ""

        for bigip in bigips:
            # need to first remove monitor reference from pool
            self.pool_helper.update(bigip, pool)

            # after updating pool, delete monitor
            hm_helper.delete(bigip,
                             name=hm["name"],
                             partition=hm["partition"])

    def update_healthmonitor(self, service, bigips):
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            hm_helper.update(bigip, hm)

            # update pool with new health monitor
            self.pool_helper.update(bigip, pool)

    # Note: can't use BigIPResourceHelper class because members
    # are created within pool objects. Following member methods
    # use the F5 SDK directly.
    def create_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        for bigip in bigips:
            part = pool["partition"]
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)
            m = p.members_s.members
            m.create(**member)

    def delete_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)

            m = p.members_s.members
            member_exists = m.exists(name=urllib.quote(member["name"]),
                                     partition=part)
            if member_exists:
                m = m.load(name=urllib.quote(member["name"]),
                           partition=part)

                m.delete()
                try:
                    node = self.service_adapter.get_member_node(service)
                    self.node_helper.delete(bigip,
                                            name=urllib.quote(node["name"]),
                                            partition=node["partition"])
                except HTTPError as err:
                    # Possilbe error if node is shared with another member.
                    # If so, ignore the error.
                    if err.response.status_code == 400:
                        LOG.debug(err.message)
                    else:
                        raise

    def update_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)

        part = pool["partition"]
        for bigip in bigips:
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]),
                           partition=part)
                member.pop("address", None)
                m.modify(**member)

    def delete_orphaned_members(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        srv_members = service['members']
        part = pool['partition']
        for bigip in bigips:
            p = self.pool_helper.load(bigip, name=pool['name'], partition=part)
            deployed_members = p.members_s.get_collection()
            for dm in deployed_members:
                orphaned = True
                for sm in srv_members:
                    svc = {"loadbalancer": service["loadbalancer"],
                           "pool": service["pool"],
                           "member": sm}
                    member = self.service_adapter.get_member(svc)
                    if member['name'] == dm.name:
                        orphaned = False
                if orphaned:
                    node_name = dm.address
                    dm.delete()
                    try:
                        self.node_helper.delete(bigip,
                                                name=urllib.quote(node_name),
                                                partition=part)
                    except HTTPError as err:
                        # Possilbe error if node is shared with another member.
                        # If so, ignore the error.
                        if err.response.status_code == 400:
                            LOG.debug(err.message)
                        else:
                            raise

    def _get_monitor_helper(self, service):
        monitor_type = self.service_adapter.get_monitor_type(service)
        if monitor_type == "HTTPS":
            hm = self.https_mon_helper
        elif monitor_type == "TCP":
            hm = self.tcp_mon_helper
        elif monitor_type == "PING":
            hm = self.ping_mon_helper
        else:
            hm = self.http_mon_helper
        return hm

    def get_member_status(self, service, bigip, status_keys):
        """Return status values for a single pool.

        Status keys to collect are defined as an array of strings in input
        status_keys.

        :param service: Has pool and member name/partition
        :param bigip: BIG-IP to get member status from.
        :param status_keys: Array of strings that define which status keys to
        collect.
        :return: A dict with key/value pairs for each status defined in
        input status_keys.
        """
        member_status = {}
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        try:
            p = self.pool_helper.load(bigip,
                                      name=pool["name"],
                                      partition=part)

            m = p.members_s.members
            if m.exists(name=urllib.quote(member["name"]), partition=part):
                m = m.load(name=urllib.quote(member["name"]), partition=part)
                member_status = self.pool_helper.collect_stats(
                    m, stat_keys=status_keys)
            else:
                LOG.error("Unable to get member status. "
                          "Member %s does not exist.", member["name"])

        except Exception as e:
            # log error but continue on
            LOG.error("Error getting member status: %s", e.message)

        return member_status
예제 #7
0
class PoolServiceBuilder(object):
    """Create LBaaS v2 pools and related objects on BIG-IPs.

    Handles requests to create, update, delete LBaaS v2 pools,
    health monitors, and members on one or more BIG-IP systems.
    """

    def __init__(self, service_adapter):
        self.service_adapter = service_adapter
        self.http_mon_helper = BigIPResourceHelper(ResourceType.http_monitor)
        self.https_mon_helper = BigIPResourceHelper(ResourceType.https_monitor)
        self.tcp_mon_helper = BigIPResourceHelper(ResourceType.tcp_monitor)
        self.ping_mon_helper = BigIPResourceHelper(ResourceType.ping_monitor)
        self.pool_helper = BigIPResourceHelper(ResourceType.pool)
        self.node_helper = BigIPResourceHelper(ResourceType.node)

    def create_pool(self, service, bigips):
        """Create a pool on set of BIG-IPs.

        Creates a BIG-IP pool to represent an LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to create Listener.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            try:
                self.pool_helper.create(bigip, pool)
            except HTTPError as err:
                LOG.error("Error creating pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

    def delete_pool(self, service, bigips):
        """Delete a pool on set of BIG-IPs.

        Deletes a BIG-IP pool defined by LBaaS pool object.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigips: Array of BigIP class instances to delete pool.
        """
        pool = self.service_adapter.get_pool(service)

        for bigip in bigips:
            try:
                self.pool_helper.delete(bigip,
                                        name=pool["name"],
                                        partition=pool["partition"])
            except HTTPError as err:
                LOG.error("Error deleting pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

    def update_pool(self, service, bigips):
        """Update BIG-IP pool.

        :param service: Dictionary which contains a both a pool
        and load balancer definition.
        :param bigip: Array of BigIP class instances to create Listener.
        """
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            try:
                self.pool_helper.update(bigip, pool)
            except HTTPError as err:
                LOG.error("Error updating pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

    def create_healthmonitor(self, service, bigips):
        # create member
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        for bigip in bigips:
            try:
                hm_helper.create(bigip, hm)
            except HTTPError as err:
                LOG.error("Error creating health monitor %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (hm["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

        # update pool with new health monitor
        pool = self.service_adapter.get_pool(service)
        for bigip in bigips:
            self.pool_helper.update(bigip, pool)

    def delete_healthmonitor(self, service, bigips):
        # delete health monitor
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)

        # update pool
        pool = self.service_adapter.get_pool(service)
        pool["monitor"] = ""

        for bigip in bigips:
            # need to first remove monitor reference from pool
            try:
                self.pool_helper.update(bigip, pool)
            except HTTPError as err:
                LOG.error("Error updating pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
            try:
                hm_helper.delete(bigip,
                                 name=hm["name"],
                                 partition=hm["partition"])
            except HTTPError as err:
                LOG.error("Error deleting health monitor %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (hm["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

    def update_healthmonitor(self, service, bigips):
        hm = self.service_adapter.get_healthmonitor(service)
        hm_helper = self._get_monitor_helper(service)
        for bigip in bigips:
            try:
                hm_helper.delete(bigip,
                                 name=hm["name"],
                                 partition=hm["partition"])
            except HTTPError as err:
                LOG.error("Error updating health monitor %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (hm["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))

    # Note: can't use BigIPResourceHelper class because members
    # are created within pool objects. Following member methods
    # use the F5 SDK directly.
    def create_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        for bigip in bigips:
            part = pool["partition"]
            try:
                p = self.pool_helper.load(bigip,
                                          name=pool["name"],
                                          partition=part)
            except HTTPError as err:
                LOG.error("Error loading pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            m = p.members_s.members
            try:
                member_exists = m.exists(name=member["name"], partition=part)
            except HTTPError as err:
                LOG.error("Error checking if member %s exists on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (member["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            if not member_exists:
                try:
                    m.create(**member)
                except HTTPError as err:
                    LOG.error("Error creating member %s on BIG-IP %s. "
                              "Repsponse status code: %s. Response "
                              "message: %s." % (member["name"],
                                                bigip.device_name,
                                                err.response.status_code,
                                                err.message))

    def delete_member(self, service, bigips):
        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            try:
                p = self.pool_helper.load(bigip,
                                          name=pool["name"],
                                          partition=part)
            except HTTPError as err:
                LOG.error("Error loading pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            m = p.members_s.members
            try:
                member_exists = m.exists(name=member["name"], partition=part)
            except HTTPError as err:
                LOG.error("Error checking if member %s exists on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (member["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            if member_exists:
                try:
                    m = m.load(name=member["name"], partition=part)
                except HTTPError as err:
                    LOG.error("Error loading member %s on BIG-IP %s. "
                              "Repsponse status code: %s. Response "
                              "message: %s." % (member["name"],
                                                bigip.device_name,
                                                err.response.status_code,
                                                err.message))
                    continue
                try:
                    m.delete()
                    node = self.service_adapter.get_member_node(service)
                    self.node_helper.delete(bigip,
                                            name=node["name"],
                                            partition=node["partition"])
                except HTTPError as err:
                    LOG.error("Error deleting member %s on BIG-IP %s. "
                              "Repsponse status code: %s. Response "
                              "message: %s." % (member["name"],
                                                bigip.device_name,
                                                err.response.status_code,
                                                err.message))

    def update_member(self, service, bigips):
        # TODO(jl) handle state -- SDK enforces at least state=None

        pool = self.service_adapter.get_pool(service)
        member = self.service_adapter.get_member(service)
        part = pool["partition"]
        for bigip in bigips:
            try:
                p = self.pool_helper.load(bigip,
                                          name=pool["name"],
                                          partition=part)
            except HTTPError as err:
                LOG.error("Error loading pool %s on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (pool["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            m = p.members_s.members
            try:
                member_exists = m.exists(name=member["name"], partition=part)
            except HTTPError as err:
                LOG.error("Error checking if member %s exists on BIG-IP %s. "
                          "Repsponse status code: %s. Response "
                          "message: %s." % (member["name"],
                                            bigip.device_name,
                                            err.response.status_code,
                                            err.message))
                continue

            if member_exists:
                try:
                    m = m.load(name=member["name"], partition=part)
                except HTTPError as err:
                    LOG.error("Error loading member %s on BIG-IP %s. "
                              "Repsponse status code: %s. Response "
                              "message: %s." % (member["name"],
                                                bigip.device_name,
                                                err.response.status_code,
                                                err.message))
                    continue
                try:
                    m.update(**member)
                except HTTPError as err:
                    LOG.error("Error updating member %s on BIG-IP %s. "
                              "Repsponse status code: %s. Response "
                              "message: %s." % (member["name"],
                                                bigip.device_name,
                                                err.response.status_code,
                                                err.message))

    def _get_monitor_helper(self, service):
        monitor_type = self.service_adapter.get_monitor_type(service)
        if monitor_type == "HTTPS":
            hm = self.https_mon_helper
        elif monitor_type == "TCP":
            hm = self.tcp_mon_helper
        elif monitor_type == "PING":
            hm = self.ping_mon_helper
        else:
            hm = self.http_mon_helper
        return hm