<s> from pulp import constants <EOL> from pulp import pulp <EOL> from pulp import solvers as pulp_solver_classes <EOL> from oslo_config import cfg <EOL> from oslo_log import log as logging <EOL> from nova . i18n import _LW <EOL> from nova_solverscheduler . scheduler import solvers as scheduler_solver <EOL> pulp_solver_opts = [ <EOL> cfg . IntOpt ( '<STR_LIT>' , <EOL> default = <NUM_LIT:20> , <EOL> help = '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) , <EOL> ] <EOL> CONF = cfg . CONF <EOL> CONF . register_opts ( pulp_solver_opts , group = '<STR_LIT>' ) <EOL> LOG = logging . getLogger ( __name__ ) <EOL> class PulpSolver ( scheduler_solver . BaseHostSolver ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> super ( PulpSolver , self ) . __init__ ( ) <EOL> self . cost_classes = self . _get_cost_classes ( ) <EOL> self . constraint_classes = self . _get_constraint_classes ( ) <EOL> def _get_cost_matrix ( self , hosts , filter_properties ) : <EOL> num_hosts = len ( hosts ) <EOL> num_instances = filter_properties . get ( '<STR_LIT>' , <NUM_LIT:1> ) <EOL> solver_cache = filter_properties [ '<STR_LIT>' ] <EOL> cost_matrix = [ [ <NUM_LIT:0> for j in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> for i in xrange ( num_hosts ) ] <EOL> solver_cache [ '<STR_LIT>' ] = cost_matrix <EOL> cost_objects = [ cost ( ) for cost in self . cost_classes ] <EOL> cost_objects . sort ( key = lambda cost : cost . precedence ) <EOL> precedence_level = <NUM_LIT:0> <EOL> for cost_object in cost_objects : <EOL> if cost_object . precedence > precedence_level : <EOL> solver_cache [ '<STR_LIT>' ] = cost_matrix <EOL> precedence_level = cost_object . precedence <EOL> cost_multiplier = cost_object . cost_multiplier ( ) <EOL> this_cost_mat = cost_object . get_extended_cost_matrix ( hosts , <EOL> filter_properties ) <EOL> if not this_cost_mat : <EOL> continue <EOL> cost_matrix = [ [ cost_matrix [ i ] [ j ] + <EOL> this_cost_mat [ i ] [ j ] * cost_multiplier <EOL> for j in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> for i in xrange ( num_hosts ) ] <EOL> solver_cache [ '<STR_LIT>' ] = cost_matrix <EOL> return cost_matrix <EOL> def _get_constraint_matrix ( self , hosts , filter_properties ) : <EOL> num_hosts = len ( hosts ) <EOL> num_instances = filter_properties . get ( '<STR_LIT>' , <NUM_LIT:1> ) <EOL> solver_cache = filter_properties [ '<STR_LIT>' ] <EOL> constraint_matrix = [ [ True for j in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> for i in xrange ( num_hosts ) ] <EOL> solver_cache [ '<STR_LIT>' ] = constraint_matrix <EOL> constraint_objects = [ cons ( ) for cons in self . constraint_classes ] <EOL> constraint_objects . sort ( key = lambda cons : cons . precedence ) <EOL> precedence_level = <NUM_LIT:0> <EOL> for constraint_object in constraint_objects : <EOL> if constraint_object . precedence > precedence_level : <EOL> solver_cache [ '<STR_LIT>' ] = constraint_matrix <EOL> precedence_level = constraint_object . precedence <EOL> this_cons_mat = constraint_object . get_constraint_matrix ( hosts , <EOL> filter_properties ) <EOL> if not this_cons_mat : <EOL> continue <EOL> for i in xrange ( num_hosts ) : <EOL> constraint_matrix [ i ] [ <NUM_LIT:1> : ] = [ constraint_matrix [ i ] [ j + <NUM_LIT:1> ] & <EOL> this_cons_mat [ i ] [ j ] for j in xrange ( num_instances ) ] <EOL> solver_cache [ '<STR_LIT>' ] = constraint_matrix <EOL> return constraint_matrix <EOL> def _adjust_cost_matrix ( self , cost_matrix ) : <EOL> """<STR_LIT>""" <EOL> new_cost_matrix = cost_matrix <EOL> if not cost_matrix : <EOL> return new_cost_matrix <EOL> first_column = [ row [ <NUM_LIT:0> ] for row in cost_matrix ] <EOL> last_column = [ row [ - <NUM_LIT:1> ] for row in cost_matrix ] <EOL> if sum ( first_column ) < sum ( last_column ) : <EOL> offset = min ( first_column ) <EOL> sign = <NUM_LIT:1> <EOL> else : <EOL> offset = max ( first_column ) <EOL> sign = - <NUM_LIT:1> <EOL> for i in xrange ( len ( cost_matrix ) ) : <EOL> for j in xrange ( len ( cost_matrix [ i ] ) ) : <EOL> new_cost_matrix [ i ] [ j ] = sign * ( <EOL> ( cost_matrix [ i ] [ j ] - offset ) ** <NUM_LIT:2> ) <EOL> return new_cost_matrix <EOL> def solve ( self , hosts , filter_properties ) : <EOL> """<STR_LIT>""" <EOL> host_instance_combinations = [ ] <EOL> num_instances = filter_properties [ '<STR_LIT>' ] <EOL> num_hosts = len ( hosts ) <EOL> instance_uuids = filter_properties . get ( '<STR_LIT>' ) or [ <EOL> '<STR_LIT>' + str ( i ) for i in xrange ( num_instances ) ] <EOL> filter_properties . setdefault ( '<STR_LIT>' , { } ) <EOL> filter_properties [ '<STR_LIT>' ] . update ( <EOL> { '<STR_LIT>' : [ ] , <EOL> '<STR_LIT>' : [ ] } ) <EOL> cost_matrix = self . _get_cost_matrix ( hosts , filter_properties ) <EOL> cost_matrix = self . _adjust_cost_matrix ( cost_matrix ) <EOL> constraint_matrix = self . _get_constraint_matrix ( hosts , <EOL> filter_properties ) <EOL> host_keys = [ '<STR_LIT>' + str ( i ) for i in xrange ( num_hosts ) ] <EOL> host_key_map = dict ( zip ( host_keys , hosts ) ) <EOL> instance_num_keys = [ '<STR_LIT>' + str ( i ) for <EOL> i in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> instance_num_key_map = dict ( zip ( instance_num_keys , <EOL> xrange ( num_instances + <NUM_LIT:1> ) ) ) <EOL> variable_matrix = [ <EOL> [ pulp . LpVariable ( '<STR_LIT>' + host_key + '<STR_LIT:_>' + instance_num_key , <EOL> <NUM_LIT:0> , <NUM_LIT:1> , constants . LpInteger ) <EOL> for instance_num_key in instance_num_keys ] <EOL> for host_key in host_keys ] <EOL> prob = pulp . LpProblem ( "<STR_LIT>" , <EOL> constants . LpMinimize ) <EOL> cost_variables = [ variable_matrix [ i ] [ j ] for i in xrange ( num_hosts ) <EOL> for j in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> cost_coefficients = [ cost_matrix [ i ] [ j ] for i in xrange ( num_hosts ) <EOL> for j in xrange ( num_instances + <NUM_LIT:1> ) ] <EOL> prob += ( pulp . lpSum ( [ cost_coefficients [ i ] * cost_variables [ i ] <EOL> for i in xrange ( len ( cost_variables ) ) ] ) , "<STR_LIT>" ) <EOL> for i in xrange ( num_hosts ) : <EOL> for j in xrange ( num_instances + <NUM_LIT:1> ) : <EOL> if constraint_matrix [ i ] [ j ] is False : <EOL> prob += ( variable_matrix [ i ] [ j ] == <NUM_LIT:0> , <EOL> "<STR_LIT>" % i + "<STR_LIT>" % j ) <EOL> prob += ( pulp . lpSum ( [ variable_matrix [ i ] [ j ] * j for i in <EOL> xrange ( num_hosts ) for j in xrange ( num_instances + <NUM_LIT:1> ) ] ) == <EOL> num_instances , "<STR_LIT>" ) <EOL> for i in xrange ( num_hosts ) : <EOL> prob += ( pulp . lpSum ( [ variable_matrix [ i ] [ j ] for j in <EOL> xrange ( num_instances + <NUM_LIT:1> ) ] ) == <NUM_LIT:1> , "<STR_LIT>" % i ) <EOL> prob . solve ( pulp_solver_classes . PULP_CBC_CMD ( <EOL> maxSeconds = CONF . solver_scheduler . pulp_solver_timeout_seconds ) ) <EOL> if pulp . LpStatus [ prob . status ] == '<STR_LIT>' : <EOL> num_insts_on_host = { } <EOL> for v in prob . variables ( ) : <EOL> if v . name . startswith ( '<STR_LIT>' ) : <EOL> ( host_key , instance_num_key ) = v . name . lstrip ( '<STR_LIT>' ) . lstrip ( <EOL> '<STR_LIT:_>' ) . split ( '<STR_LIT:_>' ) <EOL> if v . varValue == <NUM_LIT:1> : <EOL> num_insts_on_host [ host_key ] = ( <EOL> instance_num_key_map [ instance_num_key ] ) <EOL> instances_iter = iter ( instance_uuids ) <EOL> for host_key in host_keys : <EOL> num_insts_on_this_host = num_insts_on_host . get ( host_key , <NUM_LIT:0> ) <EOL> for i in xrange ( num_insts_on_this_host ) : <EOL> host_instance_combinations . append ( <EOL> ( host_key_map [ host_key ] , instances_iter . next ( ) ) ) <EOL> else : <EOL> LOG . warn ( _LW ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , pulp . LpStatus [ prob . status ] ) <EOL> host_instance_combinations = [ ] <EOL> return host_instance_combinations </s>
