Merge "Fix _poll_bandwidth_usage if no network on vif"
This commit is contained in:
@@ -2088,10 +2088,14 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
return
|
||||
|
||||
for usage in bw_usage:
|
||||
vif = usage['virtual_interface']
|
||||
mac = usage['mac_address']
|
||||
vif = self.network_api.get_vif_by_mac_address(context, mac)
|
||||
if not vif:
|
||||
continue
|
||||
|
||||
self.db.bw_usage_update(context,
|
||||
vif.instance_id,
|
||||
vif.network.label,
|
||||
vif['instance_id'],
|
||||
mac,
|
||||
start_time,
|
||||
usage['bw_in'], usage['bw_out'])
|
||||
|
||||
|
||||
+19
-1
@@ -22,6 +22,8 @@ from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import network
|
||||
from nova.network import model as network_model
|
||||
from nova.notifier import api as notifier_api
|
||||
from nova import utils
|
||||
|
||||
@@ -44,10 +46,26 @@ def notify_usage_exists(instance_ref, current_period=False):
|
||||
else:
|
||||
audit_start = begin
|
||||
audit_end = end
|
||||
|
||||
if (instance_ref.get('info_cache') and
|
||||
instance_ref['info_cache'].get('network_info')):
|
||||
|
||||
cached_info = instance_ref['info_cache']['network_info']
|
||||
nw_info = network_model.NetworkInfo.hydrate(cached_info)
|
||||
else:
|
||||
nw_info = network.API().get_instance_nw_info(admin_context,
|
||||
instance_ref)
|
||||
|
||||
for b in db.bw_usage_get_by_instance(admin_context,
|
||||
instance_ref['id'],
|
||||
audit_start):
|
||||
bw[b.network_label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
|
||||
label = 'net-name-not-found-%s' % b['mac']
|
||||
for vif in nw_info:
|
||||
if vif['address'] == b['mac']:
|
||||
label = vif['network']['label']
|
||||
break
|
||||
|
||||
bw[label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
|
||||
usage_info = utils.usage_from_instance(instance_ref,
|
||||
audit_period_beginning=str(audit_start),
|
||||
audit_period_ending=str(audit_end),
|
||||
|
||||
+2
-2
@@ -1549,14 +1549,14 @@ def bw_usage_get_all_by_filters(context, filters):
|
||||
|
||||
def bw_usage_update(context,
|
||||
instance_id,
|
||||
network_label,
|
||||
mac,
|
||||
start_period,
|
||||
bw_in, bw_out):
|
||||
"""Update cached bw usage for an instance and network
|
||||
Creates new record if needed."""
|
||||
return IMPL.bw_usage_update(context,
|
||||
instance_id,
|
||||
network_label,
|
||||
mac,
|
||||
start_period,
|
||||
bw_in, bw_out)
|
||||
|
||||
|
||||
@@ -3710,7 +3710,7 @@ def bw_usage_get_all_by_filters(context, filters):
|
||||
@require_context
|
||||
def bw_usage_update(context,
|
||||
instance_id,
|
||||
network_label,
|
||||
mac,
|
||||
start_period,
|
||||
bw_in, bw_out,
|
||||
session=None):
|
||||
@@ -3722,14 +3722,14 @@ def bw_usage_update(context,
|
||||
read_deleted="yes").\
|
||||
filter_by(instance_id=instance_id).\
|
||||
filter_by(start_period=start_period).\
|
||||
filter_by(network_label=network_label).\
|
||||
filter_by(mac=mac).\
|
||||
first()
|
||||
|
||||
if not bwusage:
|
||||
bwusage = models.BandwidthUsage()
|
||||
bwusage.instance_id = instance_id
|
||||
bwusage.start_period = start_period
|
||||
bwusage.network_label = network_label
|
||||
bwusage.mac = mac
|
||||
|
||||
bwusage.last_refreshed = utils.utcnow()
|
||||
bwusage.bw_in = bw_in
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy import *
|
||||
from migrate import *
|
||||
|
||||
from nova import utils
|
||||
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
bw_usage_cache = Table('bw_usage_cache', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('network_label', String(255)),
|
||||
Column('instance_id', Integer, nullable=False),
|
||||
Column('start_period', DateTime, nullable=False),
|
||||
Column('last_refreshed', DateTime),
|
||||
Column('bw_in', BigInteger),
|
||||
Column('bw_out', BigInteger),
|
||||
Column('created_at', DateTime(timezone=False),
|
||||
default=utils.utcnow()),
|
||||
Column('updated_at', DateTime(timezone=False),
|
||||
onupdate=utils.utcnow()),
|
||||
Column('deleted_at', DateTime(timezone=False)),
|
||||
Column('deleted', Boolean(create_constraint=True,
|
||||
name=None)))
|
||||
|
||||
vifs = Table('virtual_interfaces', meta, autoload=True)
|
||||
networks = Table('networks', meta, autoload=True)
|
||||
mac_column = Column('mac', String(255))
|
||||
|
||||
bw_usage_cache.create_column(mac_column)
|
||||
|
||||
bw_usage_cache.update()\
|
||||
.values(mac=select([vifs.c.address])\
|
||||
.where(and_(networks.c.label == bw_usage_cache.c.network_label,
|
||||
networks.c.id == vifs.c.network_id))\
|
||||
.as_scalar()).execute()
|
||||
|
||||
bw_usage_cache.c.network_label.drop()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
bw_usage_cache = Table('bw_usage_cache', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('network_uuid', String(36)),
|
||||
Column('instance_id', Integer, nullable=False),
|
||||
Column('start_period', DateTime, nullable=False),
|
||||
Column('last_refreshed', DateTime),
|
||||
Column('bw_in', BigInteger),
|
||||
Column('bw_out', BigInteger),
|
||||
Column('created_at', DateTime(timezone=False),
|
||||
default=utils.utcnow()),
|
||||
Column('updated_at', DateTime(timezone=False),
|
||||
onupdate=utils.utcnow()),
|
||||
Column('deleted_at', DateTime(timezone=False)),
|
||||
Column('deleted', Boolean(create_constraint=True,
|
||||
name=None)))
|
||||
|
||||
vifs = Table('virtual_interfaces', meta, autoload=True)
|
||||
network = Table('networks', meta, autoload=True)
|
||||
network_label_column = Column('network_label', String(255))
|
||||
|
||||
bw_usage_cache.create_column(network_label_column)
|
||||
|
||||
bw_usage_cache.update()\
|
||||
.values(network_label=select([network.c.label])\
|
||||
.where(and_(network.c.id == vifs.c.network_id,
|
||||
vifs.c.address == bw_usage_cache.c.mac))\
|
||||
.as_scalar()).execute()
|
||||
|
||||
bw_usage_cache.c.network_uuid.drop()
|
||||
@@ -927,7 +927,7 @@ class BandwidthUsage(BASE, NovaBase):
|
||||
__tablename__ = 'bw_usage_cache'
|
||||
id = Column(Integer, primary_key=True, nullable=False)
|
||||
instance_id = Column(Integer, nullable=False)
|
||||
network_label = Column(String(255))
|
||||
mac = Column(String(255), nullable=False)
|
||||
start_period = Column(DateTime, nullable=False)
|
||||
last_refreshed = Column(DateTime)
|
||||
bw_in = Column(BigInteger)
|
||||
|
||||
@@ -99,6 +99,12 @@ class API(base.Base):
|
||||
{'method': 'get_vifs_by_instance',
|
||||
'args': {'instance_id': instance['id']}})
|
||||
|
||||
def get_vif_by_mac_address(self, context, mac_address):
|
||||
return rpc.call(context,
|
||||
FLAGS.network_topic,
|
||||
{'method': 'get_vif_by_mac_address',
|
||||
'args': {'mac_address': mac_address}})
|
||||
|
||||
def allocate_floating_ip(self, context, pool=None):
|
||||
"""Adds a floating ip to a project from a pool. (allocates)"""
|
||||
# NOTE(vish): We don't know which network host should get the ip
|
||||
|
||||
@@ -1476,6 +1476,11 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
fixed = self.db.fixed_ip_get(context, id)
|
||||
return dict(fixed.iteritems())
|
||||
|
||||
def get_vif_by_mac_address(self, context, mac_address):
|
||||
"""Returns the vifs record for the mac_address"""
|
||||
return self.db.virtual_interface_get_by_address(context,
|
||||
mac_address)
|
||||
|
||||
|
||||
class FlatManager(NetworkManager):
|
||||
"""Basic network where no vlans are used.
|
||||
|
||||
+75
-26
@@ -190,6 +190,15 @@ class BaseTestCase(test.TestCase):
|
||||
|
||||
|
||||
class ComputeTestCase(BaseTestCase):
|
||||
def setUp(self):
|
||||
def fake_get_nw_info(cls, ctxt, instance):
|
||||
self.assertTrue(ctxt.is_admin)
|
||||
return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
|
||||
spectacular=True)
|
||||
|
||||
super(ComputeTestCase, self).setUp()
|
||||
self.stubs.Set(nova.network.API, 'get_instance_nw_info',
|
||||
fake_get_nw_info)
|
||||
|
||||
def test_wrap_instance_fault(self):
|
||||
inst_uuid = "fake_uuid"
|
||||
@@ -966,38 +975,66 @@ class ComputeTestCase(BaseTestCase):
|
||||
def test_finish_resize(self):
|
||||
"""Contrived test to ensure finish_resize doesn't raise anything"""
|
||||
|
||||
nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
|
||||
def fake(*args, **kwargs):
|
||||
pass
|
||||
|
||||
def fake_nw_info(*args, **kwargs):
|
||||
return nw_info
|
||||
|
||||
# NOTE(jkoelker) There is a bit of a stubbing issue here.
|
||||
# fake_network stubs out a bunch of stuff which
|
||||
# this functional test expects to be acting on
|
||||
# the db or the stubs it sets.
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.SmartUnsetAll()
|
||||
self.setUp()
|
||||
|
||||
self.stubs.Set(self.compute.driver, 'finish_migration', fake)
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
|
||||
fake_nw_info)
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
func=fake_nw_info)
|
||||
context = self.context.elevated()
|
||||
|
||||
instance = self._create_fake_instance()
|
||||
self.compute.prep_resize(context, instance['uuid'], 1,
|
||||
filter_properties={})
|
||||
migration_ref = db.migration_get_by_instance_and_status(context,
|
||||
instance['uuid'], 'pre-migrating')
|
||||
try:
|
||||
self.compute.finish_resize(context, instance['uuid'],
|
||||
int(migration_ref['id']), {})
|
||||
except KeyError, e:
|
||||
# Only catch key errors. We want other reasons for the test to
|
||||
# fail to actually error out so we don't obscure anything
|
||||
self.fail()
|
||||
|
||||
self.compute.finish_resize(context, instance['uuid'],
|
||||
int(migration_ref['id']), {})
|
||||
self.compute.terminate_instance(self.context, instance['uuid'])
|
||||
|
||||
def test_finish_resize_handles_error(self):
|
||||
"""Make sure we don't leave the instance in RESIZE on error"""
|
||||
|
||||
nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
|
||||
def throw_up(*args, **kwargs):
|
||||
raise Exception()
|
||||
|
||||
def fake(*args, **kwargs):
|
||||
pass
|
||||
|
||||
def fake_nw_info(*args, **kwargs):
|
||||
return nw_info
|
||||
|
||||
# NOTE(jkoelker) There is a bit of a stubbing issue here.
|
||||
# fake_network stubs out a bunch of stuff which
|
||||
# this functional test expects to be acting on
|
||||
# the db or the stubs it sets.
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.SmartUnsetAll()
|
||||
self.setUp()
|
||||
|
||||
self.stubs.Set(self.compute.driver, 'finish_migration', throw_up)
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
func=fake_nw_info)
|
||||
context = self.context.elevated()
|
||||
instance = self._create_fake_instance()
|
||||
self.compute.prep_resize(context, instance['uuid'], 1,
|
||||
@@ -1123,13 +1160,32 @@ class ComputeTestCase(BaseTestCase):
|
||||
|
||||
def test_finish_revert_resize(self):
|
||||
"""Ensure that the flavor is reverted to the original on revert"""
|
||||
context = self.context.elevated()
|
||||
instance = self._create_fake_instance()
|
||||
instance_uuid = instance['uuid']
|
||||
nw_info = fake_network.fake_get_instance_nw_info(self.stubs,
|
||||
spectacular=True)
|
||||
|
||||
def fake(*args, **kwargs):
|
||||
pass
|
||||
|
||||
def fake_nw_info(*args, **kwargs):
|
||||
return nw_info
|
||||
|
||||
# NOTE(jkoelker) There is a bit of a stubbing issue here.
|
||||
# fake_network stubs out a bunch of stuff which
|
||||
# this functional test expects to be acting on
|
||||
# the db or the stubs it sets.
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.SmartUnsetAll()
|
||||
self.setUp()
|
||||
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
|
||||
fake_nw_info)
|
||||
fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs,
|
||||
func=fake_nw_info)
|
||||
|
||||
context = self.context.elevated()
|
||||
instance = self._create_fake_instance()
|
||||
instance_uuid = instance['uuid']
|
||||
|
||||
self.stubs.Set(self.compute.driver, 'finish_migration', fake)
|
||||
self.stubs.Set(self.compute.driver, 'finish_revert_migration', fake)
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
|
||||
@@ -1450,7 +1506,14 @@ class ComputeTestCase(BaseTestCase):
|
||||
class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
def fake_get_nw_info(cls, ctxt, instance):
|
||||
self.assertTrue(ctxt.is_admin)
|
||||
return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
|
||||
spectacular=True)
|
||||
|
||||
super(ComputeAPITestCase, self).setUp()
|
||||
self.stubs.Set(nova.network.API, 'get_instance_nw_info',
|
||||
fake_get_nw_info)
|
||||
self.compute_api = compute.API()
|
||||
self.fake_image = {
|
||||
'id': 1,
|
||||
@@ -2267,17 +2330,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
fixed_address):
|
||||
called['associate'] = True
|
||||
|
||||
def fake_get_nw_info(cls, ctxt, instance):
|
||||
self.assertTrue(ctxt.is_admin)
|
||||
return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
|
||||
spectacular=True)
|
||||
|
||||
self.stubs.Set(nova.network.API, 'associate_floating_ip',
|
||||
fake_associate_ip_network_api)
|
||||
|
||||
self.stubs.Set(nova.network.API, 'get_instance_nw_info',
|
||||
fake_get_nw_info)
|
||||
|
||||
instance = self._create_fake_instance()
|
||||
instance_uuid = instance['uuid']
|
||||
address = '0.1.2.3'
|
||||
@@ -2995,12 +3050,6 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertTrue(self.compute_api.get_lock(self.context, instance))
|
||||
|
||||
def test_add_remove_security_group(self):
|
||||
def fake_get_nw_info(cls, ctxt, instance):
|
||||
return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
|
||||
spectacular=True)
|
||||
|
||||
self.stubs.Set(nova.network.API, 'get_instance_nw_info',
|
||||
fake_get_nw_info)
|
||||
instance = self._create_fake_instance()
|
||||
|
||||
self.compute.run_instance(self.context, instance['uuid'])
|
||||
|
||||
@@ -29,6 +29,7 @@ import nova.image.fake
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import instance_types
|
||||
from nova.notifier import test_notifier
|
||||
from nova.tests import fake_network
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.tests.compute_utils')
|
||||
@@ -39,7 +40,15 @@ flags.DECLARE('stub_network', 'nova.compute.manager')
|
||||
class UsageInfoTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
def fake_get_nw_info(cls, ctxt, instance):
|
||||
self.assertTrue(ctxt.is_admin)
|
||||
return fake_network.fake_get_instance_nw_info(self.stubs, 1, 1,
|
||||
spectacular=True)
|
||||
|
||||
super(UsageInfoTestCase, self).setUp()
|
||||
self.stubs.Set(nova.network.API, 'get_instance_nw_info',
|
||||
fake_get_nw_info)
|
||||
|
||||
self.flags(connection_type='fake',
|
||||
stub_network=True,
|
||||
notification_driver='nova.notifier.test_notifier',
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import stubout
|
||||
|
||||
import nova
|
||||
import nova.notifier.no_op_notifier
|
||||
from nova import log
|
||||
import nova.notifier.api
|
||||
from nova.notifier.api import notify
|
||||
@@ -26,6 +27,7 @@ class NotifierTestCase(test.TestCase):
|
||||
"""Test case for notifications"""
|
||||
def setUp(self):
|
||||
super(NotifierTestCase, self).setUp()
|
||||
self.flags(notification_driver='nova.notifier.no_op_notifier')
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
@@ -46,7 +46,8 @@ class QuotaTestCase(test.TestCase):
|
||||
quota_cores=4,
|
||||
quota_volumes=2,
|
||||
quota_gigabytes=20,
|
||||
quota_floating_ips=1)
|
||||
quota_floating_ips=1,
|
||||
network_manager='nova.network.manager.FlatDHCPManager')
|
||||
|
||||
self.network = self.network = self.start_service('network')
|
||||
self.user_id = 'admin'
|
||||
|
||||
@@ -328,13 +328,9 @@ class XenAPIConnection(driver.ComputeDriver):
|
||||
for iusage in self._vmops.get_all_bw_usage(start_time, stop_time).\
|
||||
values():
|
||||
for macaddr, usage in iusage.iteritems():
|
||||
vi = db.virtual_interface_get_by_address(
|
||||
context.get_admin_context(),
|
||||
macaddr)
|
||||
if vi:
|
||||
bwusage.append(dict(virtual_interface=vi,
|
||||
bw_in=usage['bw_in'],
|
||||
bw_out=usage['bw_out']))
|
||||
bwusage.append(dict(mac_address=macaddr,
|
||||
bw_in=usage['bw_in'],
|
||||
bw_out=usage['bw_out']))
|
||||
return bwusage
|
||||
|
||||
def get_console_output(self, instance):
|
||||
|
||||
Reference in New Issue
Block a user