Use DB ports instead of fetching from driver

We have saved node ports information to DB, so change to use it
instead of issuing an extra API request.

Change-Id: I5b9183a1afdcb1e9444a88dfa50e1c31bf54e805
This commit is contained in:
Zhenguo Niu 2017-03-24 17:54:43 +08:00
parent 32d9bf7a11
commit e173d1f432
10 changed files with 36 additions and 26 deletions

View File

@ -115,6 +115,7 @@ def upgrade():
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('address', sa.String(length=18), nullable=False),
sa.Column('port_type', sa.String(length=255), nullable=False),
sa.Column('port_uuid', sa.String(length=36), nullable=False),
sa.Column('node_uuid', sa.String(length=36), nullable=False),

View File

@ -119,6 +119,7 @@ class ComputePort(Base):
table_args()
)
id = Column(Integer, primary_key=True)
address = Column(String(18), nullable=False)
port_type = Column(String(255), nullable=False)
port_uuid = Column(String(36), nullable=False)
node_uuid = Column(String(36), nullable=False)

View File

@ -161,6 +161,7 @@ class IronicDriver(base_driver.BaseEngineDriver):
port_type = port.extra.get('port_type')
dic = {
'address': str(port.address),
'port_type': str(port_type),
'node_uuid': str(port.node_uuid),
'port_uuid': str(port.uuid),

View File

@ -116,38 +116,36 @@ class BuildNetworkTask(flow_utils.MoganTask):
"""Build network for the instance."""
def __init__(self, manager):
requires = ['instance', 'requested_networks', 'context']
requires = ['instance', 'requested_networks', 'ports', 'context']
super(BuildNetworkTask, self).__init__(addons=[ACTION],
requires=requires)
self.manager = manager
def _build_networks(self, context, instance, requested_networks):
node_uuid = instance.node_uuid
bm_ports = self.manager.driver.get_ports_from_node(node_uuid,
detail=True)
def _build_networks(self, context, instance, requested_networks, ports):
LOG.debug(_('Find ports %(ports)s for node %(node)s') %
{'ports': bm_ports, 'node': node_uuid})
if len(requested_networks) > len(bm_ports):
# TODO(zhenguo): This seems not needed as our scheduler has already
# guaranteed this.
if len(requested_networks) > len(ports):
raise exception.InterfacePlugException(_(
"Ironic node: %(id)s virtual to physical interface count"
" mismatch"
" (Vif count: %(vif_count)d, Pif count: %(pif_count)d)")
% {'id': instance.node_uuid,
'vif_count': len(requested_networks),
'pif_count': len(bm_ports)})
'pif_count': len(ports)})
nics_obj = objects.InstanceNics(context)
for vif in requested_networks:
for pif in bm_ports:
for pif in ports:
# Match the specified port type with physical interface type
if vif.get('port_type') == pif.extra.get('port_type'):
if vif.get('port_type', 'None') == pif.port_type:
try:
port = self.manager.network_api.create_port(
context, vif['net_id'], pif.address, instance.uuid)
port_dict = port['port']
self.manager.driver.plug_vif(pif.uuid, port_dict['id'])
self.manager.driver.plug_vif(pif.port_uuid,
port_dict['id'])
nic_dict = {'port_id': port_dict['id'],
'network_id': port_dict['network_id'],
'mac_address': port_dict['mac_address'],
@ -167,11 +165,12 @@ class BuildNetworkTask(flow_utils.MoganTask):
"Build network for instance failed."))
return nics_obj
def execute(self, context, instance, requested_networks):
def execute(self, context, instance, requested_networks, ports):
instance_nics = self._build_networks(
context,
instance,
requested_networks)
requested_networks,
ports)
instance.nics = instance_nics
instance.save()
@ -219,8 +218,8 @@ class CreateInstanceTask(flow_utils.MoganTask):
return False
def get_flow(context, manager, instance, requested_networks, request_spec,
filter_properties):
def get_flow(context, manager, instance, requested_networks, ports,
request_spec, filter_properties):
"""Constructs and returns the manager entrypoint flow
@ -242,7 +241,8 @@ def get_flow(context, manager, instance, requested_networks, request_spec,
'filter_properties': filter_properties,
'request_spec': request_spec,
'instance': instance,
'requested_networks': requested_networks
'requested_networks': requested_networks,
'ports': ports
}
instance_flow.add(OnFailureRescheduleTask(manager.engine_rpcapi),

View File

@ -330,7 +330,7 @@ class EngineManager(base_manager.BaseEngineManager):
instance.save()
except Exception as e:
utils.process_event(fsm, instance, event='error')
LOG.error("Created instance %(uuid)s failed."
LOG.error("Created instance %(uuid)s failed. "
"Exception: %(exception)s",
{"uuid": instance.uuid,
"exception": e})
@ -342,6 +342,7 @@ class EngineManager(base_manager.BaseEngineManager):
self,
instance,
requested_networks,
node['ports'],
request_spec,
filter_properties,
)

View File

@ -30,6 +30,7 @@ class ComputePort(base.MoganObject, object_base.VersionedObjectDictCompat):
fields = {
'id': object_fields.IntegerField(read_only=True),
'address': object_fields.MACAddressField(nullable=False),
'port_type': object_fields.StringField(),
'port_uuid': object_fields.UUIDField(read_only=True),
'node_uuid': object_fields.UUIDField(read_only=True),
@ -73,7 +74,8 @@ class ComputePort(base.MoganObject, object_base.VersionedObjectDictCompat):
self.obj_refresh(current)
def update_from_driver(self, port):
keys = ["port_type", "port_uuid", "node_uuid", "extra_specs"]
keys = ["address", "port_type", "port_uuid", "node_uuid",
"extra_specs"]
for key in keys:
if key in port:
setattr(self, key, port[key])

View File

@ -185,10 +185,10 @@ class FilterScheduler(driver.Scheduler):
request_spec.get('instance_type'))
raise exception.NoValidNode(_("No weighed nodes available"))
top_node = self._choose_top_node(weighed_nodes, request_spec)
top_node.obj.consume_from_request(context)
self._add_retry_node(filter_properties, top_node.obj.node_uuid)
dest = dict(node_uuid=top_node.obj.node_uuid)
node = self._choose_top_node(weighed_nodes, request_spec)
node.obj.consume_from_request(context)
self._add_retry_node(filter_properties, node.obj.node_uuid)
dest = dict(node_uuid=node.obj.node_uuid, ports=node.obj.ports)
return dest
return _schedule(self, context, request_spec, filter_properties)

View File

@ -129,6 +129,7 @@ def create_test_compute_node(context={}, **kw):
def get_test_compute_port(**kw):
return {
'id': kw.get('id', 123),
'address': kw.get('address', '52:54:00:cf:2d:31'),
'port_type': kw.get('port_type', '1GE'),
'port_uuid': kw.get('port_uuid',
'f978ef48-d4af-4dad-beec-e6174309bc72'),

View File

@ -36,15 +36,18 @@ class CreateInstanceFlowTestCase(base.TestCase):
def test_create_network_task_execute(self, mock_build_networks, mock_save):
fake_engine_manager = mock.MagicMock()
fake_requested_networks = mock.MagicMock()
fake_ports = mock.MagicMock()
task = create_instance.BuildNetworkTask(fake_engine_manager)
instance_obj = obj_utils.get_test_instance(self.ctxt)
mock_build_networks.return_value = None
mock_save.return_value = None
task.execute(self.ctxt, instance_obj, fake_requested_networks)
task.execute(
self.ctxt, instance_obj, fake_requested_networks, fake_ports)
mock_build_networks.assert_called_once_with(self.ctxt,
instance_obj,
fake_requested_networks)
fake_requested_networks,
fake_ports)
@mock.patch.object(IronicDriver, 'spawn')
def test_create_instance_task_execute(self, mock_spawn):

View File

@ -385,7 +385,7 @@ expected_object_fingerprints = {
'Instance': '1.0-a4d843f506946e824fe6accb842e0a84',
'ComputeNode': '1.0-36221253681d9acb88efe2a9113071c7',
'ComputeNodeList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
'ComputePort': '1.0-bdba0f3ece31260c4deea37d39618c1a',
'ComputePort': '1.0-ca4c1817ad7324286813f2cfcdcf802e',
'ComputePortList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
'InstanceFault': '1.0-6b5b01b2cc7b6b547837acb168ec6eb9',
'InstanceFaultList': '1.0-43e8aad0258652921f929934e9e048fd',