<s> import abc <EOL> from datetime import timedelta <EOL> from operator import itemgetter <EOL> import random <EOL> import six <EOL> from oslo_log import log as logging <EOL> from sqlalchemy import func <EOL> from sqlalchemy . sql import expression as expr <EOL> from networking_cisco . plugins . cisco . common import cisco_constants <EOL> from networking_cisco . plugins . cisco . db . device_manager import hd_models <EOL> LOG = logging . getLogger ( __name__ ) <EOL> ROUTER_ROLE_HA_REDUNDANCY = cisco_constants . ROUTER_ROLE_HA_REDUNDANCY <EOL> EQUIVALENCE_TIME_DIFF = <NUM_LIT:7> <EOL> @ six . add_metaclass ( abc . ABCMeta ) <EOL> class L3RouterHostingDeviceBaseScheduler ( object ) : <EOL> """<STR_LIT>""" <EOL> def get_candidates ( self , plugin , context , r_hd_binding_db ) : <EOL> """<STR_LIT>""" <EOL> router = r_hd_binding_db . router <EOL> tenant_id = router [ '<STR_LIT>' ] <EOL> router_type_db = r_hd_binding_db . router_type <EOL> template_id = router_type_db [ '<STR_LIT>' ] <EOL> template_db = router_type_db . template <EOL> slot_threshold = template_db . slot_capacity - router_type_db . slot_need <EOL> query = context . session . query ( <EOL> hd_models . HostingDevice . id , hd_models . HostingDevice . created_at , <EOL> func . sum ( hd_models . SlotAllocation . num_allocated ) ) <EOL> query = query . outerjoin ( <EOL> hd_models . SlotAllocation , <EOL> hd_models . HostingDevice . id == <EOL> hd_models . SlotAllocation . hosting_device_id ) <EOL> query = query . filter ( <EOL> hd_models . HostingDevice . template_id == template_id , <EOL> hd_models . HostingDevice . admin_state_up == expr . true ( ) , <EOL> hd_models . HostingDevice . status == cisco_constants . HD_ACTIVE ) <EOL> if r_hd_binding_db . share_hosting_device : <EOL> query = query . filter ( <EOL> expr . or_ ( hd_models . HostingDevice . tenant_bound == expr . null ( ) , <EOL> hd_models . HostingDevice . tenant_bound == tenant_id ) ) <EOL> else : <EOL> query = query . filter ( <EOL> expr . or_ ( <EOL> hd_models . SlotAllocation . tenant_bound == tenant_id , <EOL> expr . and_ ( <EOL> hd_models . SlotAllocation . tenant_bound == expr . null ( ) , <EOL> hd_models . SlotAllocation . logical_resource_owner == <EOL> tenant_id ) , <EOL> hd_models . HostingDevice . tenant_bound == tenant_id , <EOL> expr . and_ ( <EOL> hd_models . HostingDevice . tenant_bound == expr . null ( ) , <EOL> hd_models . SlotAllocation . hosting_device_id == <EOL> expr . null ( ) ) ) ) <EOL> query = query . group_by ( hd_models . HostingDevice . id ) <EOL> query = query . having ( <EOL> expr . or_ ( func . sum ( <EOL> hd_models . SlotAllocation . num_allocated ) <= slot_threshold , <EOL> func . sum ( hd_models . SlotAllocation . num_allocated == <EOL> expr . null ( ) ) ) ) <EOL> query = query . order_by ( hd_models . HostingDevice . created_at ) <EOL> return query . all ( ) <EOL> @ abc . abstractmethod <EOL> def schedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> pass <EOL> @ abc . abstractmethod <EOL> def unschedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> pass <EOL> class L3RouterHostingDeviceLongestRunningScheduler ( <EOL> L3RouterHostingDeviceBaseScheduler ) : <EOL> """<STR_LIT>""" <EOL> def schedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> candidates = self . _filtered_candidates ( plugin , context , <EOL> r_hd_binding_db ) <EOL> if len ( candidates ) == <NUM_LIT:0> : <EOL> return <EOL> oldest_candidates = [ ] <EOL> minute_limit = timedelta ( minutes = EQUIVALENCE_TIME_DIFF ) <EOL> for candidate in candidates : <EOL> if candidate [ <NUM_LIT:1> ] - candidates [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] < minute_limit : <EOL> oldest_candidates . append ( candidate ) <EOL> else : <EOL> break <EOL> sorted_candidates = sorted ( oldest_candidates , key = itemgetter ( <NUM_LIT:2> ) ) <EOL> return sorted_candidates [ <NUM_LIT:0> ] <EOL> def unschedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> return True <EOL> def _filtered_candidates ( self , plugin , context , r_hd_binding_db ) : <EOL> return self . get_candidates ( plugin , context , r_hd_binding_db ) <EOL> class CandidatesHAFilterMixin ( object ) : <EOL> def _filtered_candidates ( self , plugin , context , r_hd_binding_db ) : <EOL> candidates_dict = { c . id : c for c in self . get_candidates ( <EOL> plugin , context , r_hd_binding_db ) } <EOL> if candidates_dict : <EOL> r_b = r_hd_binding_db . router . redundancy_binding <EOL> if r_b : <EOL> if r_b . user_router . hosting_info . hosting_device_id : <EOL> del candidates_dict [ <EOL> r_b . user_router . hosting_info . hosting_device_id ] <EOL> for rr_b in r_b . user_router . redundancy_bindings : <EOL> rr = rr_b . redundancy_router <EOL> if ( rr . id != r_b . redundancy_router_id and <EOL> rr . hosting_info . hosting_device_id ) : <EOL> del candidates_dict [ rr . hosting_info . hosting_device_id ] <EOL> elif r_hd_binding_db . role == ROUTER_ROLE_HA_REDUNDANCY : <EOL> return [ ] <EOL> for rr_b in r_hd_binding_db . router . redundancy_bindings : <EOL> rr = rr_b . redundancy_router <EOL> if rr . hosting_info . hosting_device_id : <EOL> del candidates_dict [ rr . hosting_info . hosting_device_id ] <EOL> return candidates_dict . values ( ) <EOL> class L3RouterHostingDeviceHALongestRunningScheduler ( <EOL> CandidatesHAFilterMixin , L3RouterHostingDeviceLongestRunningScheduler ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> class L3RouterHostingDeviceRandomScheduler ( L3RouterHostingDeviceBaseScheduler ) : <EOL> """<STR_LIT>""" <EOL> def schedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> candidates = self . _filtered_candidates ( plugin , context , <EOL> r_hd_binding_db ) <EOL> if len ( candidates ) == <NUM_LIT:0> : <EOL> return <EOL> return random . choice ( list ( candidates ) ) <EOL> def unschedule_router ( self , plugin , context , r_hd_binding_db ) : <EOL> return True <EOL> def _filtered_candidates ( self , plugin , context , r_hd_binding ) : <EOL> return self . get_candidates ( plugin , context , r_hd_binding ) <EOL> class L3RouterHostingDeviceHARandomScheduler ( <EOL> CandidatesHAFilterMixin , L3RouterHostingDeviceRandomScheduler ) : <EOL> """<STR_LIT>""" <EOL> pass </s>
