Skip to content

Commit

Permalink
staged changes
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminLudwigSAP committed Nov 4, 2024
1 parent beb0772 commit f440c6f
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 27 deletions.
4 changes: 4 additions & 0 deletions octavia_f5/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ def setup_logging(conf):
item_type=cfg.types.URI(schemes=['http', 'https']),
default=[],
help=_('The URL of the bigip vcmp host devices')),
cfg.BoolOpt('vcmp_rseries',
default=False,
help=_("Whether the BigIP vcmp host device belongs to the "
"r-Series and thus uses the F5OS-A API")),
cfg.ListOpt('override_vcmp_guest_names',
default=[],
help=_('List of vcmp guest names to use for identifying the '
Expand Down
32 changes: 16 additions & 16 deletions octavia_f5/controller/worker/controller_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,24 @@ class ControllerWorker(object):
'octavia_as3_worker_queue', 'Number of items in AS3 worker queue', ['octavia_host'])

def __init__(self):
self._repositories = repo.Repositories()
self._loadbalancer_repo = f5_repos.LoadBalancerRepository()
self._amphora_repo = repo.AmphoraRepository()
self._health_mon_repo = repo.HealthMonitorRepository()
self._listener_repo = f5_repos.ListenerRepository()
self._member_repo = repo.MemberRepository()
self._pool_repo = f5_repos.PoolRepository()
self._l7policy_repo = f5_repos.L7PolicyRepository()
self._l7rule_repo = repo.L7RuleRepository()
self._vip_repo = repo.VipRepository()
self._quota_repo = f5_repos.QuotasRepository()
self._az_repo = repo.AvailabilityZoneRepository()
self._azp_repo = repo.AvailabilityZoneProfileRepository()
self.queue = SetQueue()
# self._repositories = repo.Repositories()
# self._loadbalancer_repo = f5_repos.LoadBalancerRepository()
# self._amphora_repo = repo.AmphoraRepository()
# self._health_mon_repo = repo.HealthMonitorRepository()
# self._listener_repo = f5_repos.ListenerRepository()
# self._member_repo = repo.MemberRepository()
# self._pool_repo = f5_repos.PoolRepository()
# self._l7policy_repo = f5_repos.L7PolicyRepository()
# self._l7rule_repo = repo.L7RuleRepository()
# self._vip_repo = repo.VipRepository()
# self._quota_repo = f5_repos.QuotasRepository()
# self._az_repo = repo.AvailabilityZoneRepository()
# self._azp_repo = repo.AvailabilityZoneProfileRepository()
# self.queue = SetQueue()

# instantiate managers/drivers
self.status = status_manager.StatusManager()
self.sync = sync_manager.SyncManager(self.status, self._loadbalancer_repo)
# self.status = status_manager.StatusManager()
# self.sync = sync_manager.SyncManager(self.status, self._loadbalancer_repo)
self.l2sync = l2_sync_manager.L2SyncManager()
self.network_driver = driver_utils.get_network_driver()

Expand Down
9 changes: 8 additions & 1 deletion octavia_f5/controller/worker/flows/f5_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@
# License for the specific language governing permissions and limitations
# under the License.

from oslo_config import cfg
from oslo_log import log as logging
from taskflow import flow
from taskflow.patterns import unordered_flow, linear_flow

from octavia.network import data_models as network_models
from octavia_f5.controller.worker.tasks import f5_tasks
from octavia_f5.controller.worker.tasks import f5_tasks, f5_tasks_rseries

CONF = cfg.CONF
LOG = logging.getLogger(__name__)


class F5Flows(object):

def __init__(self):#, f5os_a_api=CONF.networking.vcmp_rseries):
self.f5os_a_api = False#f5os_a_api
# TODO use f5os_a_api to distinguish, which tasks to use

def make_ensure_l2_flow(self, selfips: [network_models.Port], store: dict) -> flow.Flow:
"""
Construct and return a flow to ensure complete L2 configuration for a new partition.
Expand Down
11 changes: 7 additions & 4 deletions octavia_f5/controller/worker/l2_sync_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,20 @@ class L2SyncManager(BaseTaskFlowEngine):
_metric_failed_futures = prometheus.metrics.Counter(
'octavia_l2_failed_futures', 'Failed l2 task futures', ['device', 'task'])

def __init__(self):
def __init__(self, foo=CONF.networking.vcmp_urls):
super(L2SyncManager).__init__()
self._bigips = list(self.initialize_bigips(CONF.f5_agent.bigip_urls))
self._vcmps = list(self.initialize_bigips(CONF.networking.vcmp_urls))
self._vcmps = list(self.initialize_bigips(CONF.networking.vcmp_urls,
r_series_vcmp_host=CONF.networking.vcmp_rseries))
self._f5flows = f5_flows.F5Flows()
self._network_driver = driver_utils.get_network_driver()
self.executor = futures.ThreadPoolExecutor(max_workers=CONF.networking.max_workers)

def initialize_bigips(self, bigip_urls: [str]):
def initialize_bigips(self, bigip_urls: [str], r_series_vcmp_host=False):
"""
Initialize a BigIP client. This is used for both, vCMP hosts and guests.
:param r_series_vcmp_host: Whether we're initializing rSeries vCMP hosts
"""

if CONF.f5_agent.dry_run:
Expand All @@ -66,7 +69,7 @@ def initialize_bigips(self, bigip_urls: [str]):
'verify': CONF.f5_agent.bigip_verify}

if CONF.f5_agent.bigip_token:
kwargs['auth'] = bigip_auth.BigIPTokenAuth(bigip_url)
kwargs['auth'] = bigip_auth.BigIPTokenAuth(bigip_url, r_series=r_series_vcmp_host)
else:
kwargs['auth'] = bigip_auth.BigIPBasicAuth(bigip_url)

Expand Down
22 changes: 16 additions & 6 deletions octavia_f5/restclient/bigip/bigip_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
from requests.auth import HTTPBasicAuth, AuthBase

BIGIP_TOKEN_HEADER = 'X-F5-Auth-Token'
BIGIP_TOKEN_HEADER_F5OS_A = 'X-Auth-Token'
BIGIP_TOKEN_MAX_TIMEOUT = '36000'
# FIXME What's the equivalent for F5OS-A?
BIGIP_TOKENS_PATH = '/mgmt/shared/authz/tokens'
BIGIP_LOGIN_PATH = '/mgmt/shared/authn/login'
BIGIP_LOGIN_PATH_F5OS_A = '/data/openconfig-system:system/aaa'


class BigIPBasicAuth(HTTPBasicAuth):
Expand All @@ -36,13 +39,17 @@ def __init__(self, url):
class BigIPTokenAuth(AuthBase):
""" A requests custom Auth provider that installs a response hook to detect authentication
responses and acquires a BigIP authentication token for follow up http requests. """
def __init__(self, url):

def __init__(self, url, r_series=False):
self.url = url
parse_result = parse.urlparse(url, allow_fragments=False)
self.username = parse_result.username
self.password = parse.unquote(parse_result.password)
self.f5os_a = r_series
# Use single global token
self.token = None
self._token_endpoint = BIGIP_LOGIN_PATH if not r_series else BIGIP_LOGIN_PATH_F5OS_A
self._token_header = BIGIP_TOKEN_HEADER if not r_series else BIGIP_TOKEN_HEADER_F5OS_A

def handle_401(self, r, **kwargs):
""" This response hook will fetch a fresh token if encountered an 401 response code.
Expand All @@ -60,7 +67,7 @@ def handle_401(self, r, **kwargs):
r.content
r.raw.release_conn()
prep = r.request.copy()
prep.headers[BIGIP_TOKEN_HEADER] = self.get_token()
prep.headers[self._token_header] = self.get_token()

_r = r.connection.send(prep, **kwargs)
_r.history.append(r)
Expand All @@ -71,7 +78,7 @@ def handle_401(self, r, **kwargs):
def __call__(self, r):
# No token, no fun
if self.token:
r.headers[BIGIP_TOKEN_HEADER] = self.token
r.headers[self._token_header] = self.token

# handle 401 case
r.register_hook('response', self.handle_401)
Expand All @@ -85,21 +92,24 @@ def get_token(self):
""" Get F5-Auth-Token
https://clouddocs.f5.com/products/extensions/f5-declarative-onboarding/latest/authentication.html
"""

credentials = {
"username": self.username,
"password": self.password,
"loginProviderName": "tmos"
}
if not self.f5os_a:
credentials["loginProviderName"] = "tmos"
auth = (self.username, self.password)

r = requests.post(parse.urljoin(self.url, BIGIP_LOGIN_PATH),
r = requests.post(parse.urljoin(self.url, self._token_endpoint),
json=credentials, auth=auth, timeout=10, verify=False)

# Handle maximum active login tokens condition
if r.status_code == 400 and 'maximum active login tokens' in r.text:
# Delete all existing tokens
# TODO what is happening here? Does this have an equivalent in F5OS-A?
requests.delete(parse.urljoin(self.url, BIGIP_TOKENS_PATH), auth=auth, timeout=10, verify=False)
r = requests.post(parse.urljoin(self.url, BIGIP_LOGIN_PATH), json=credentials,
r = requests.post(parse.urljoin(self.url, self._token_endpoint), json=credentials,
auth=auth, timeout=10, verify=False)

r.raise_for_status()
Expand Down

0 comments on commit f440c6f

Please sign in to comment.