summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrey Morris <trey.morris@rackspace.com>2011-03-14 13:32:22 -0500
committerTrey Morris <trey.morris@rackspace.com>2011-03-14 13:32:22 -0500
commit093c8200a102891232e2da166830cd59ee133fc4 (patch)
treef07ed6dac0a7e83fe9bf6adf6dc4b4ea0d3da02d
parent18e16ab9f5be77764a810b2d6ac5ae8c5be6bb52 (diff)
downloadnova-093c8200a102891232e2da166830cd59ee133fc4.tar.gz
nova-093c8200a102891232e2da166830cd59ee133fc4.tar.xz
nova-093c8200a102891232e2da166830cd59ee133fc4.zip
committing to share
-rwxr-xr-xbin/nova-manage8
-rw-r--r--nova/compute/api.py3
-rw-r--r--nova/compute/manager.py12
-rw-r--r--nova/db/api.py39
-rw-r--r--nova/db/sqlalchemy/api.py131
-rw-r--r--nova/db/sqlalchemy/models.py76
-rw-r--r--nova/exception.py4
-rw-r--r--nova/network/api.py6
-rw-r--r--nova/network/manager.py61
-rw-r--r--nova/tests/test_compute.py1
-rw-r--r--nova/tests/test_quota.py1
-rw-r--r--nova/tests/test_scheduler.py1
-rw-r--r--nova/tests/test_volume.py1
-rw-r--r--nova/utils.py8
14 files changed, 270 insertions, 82 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index b603c8b07..9dc0f4a62 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -505,7 +505,8 @@ class NetworkCommands(object):
def create(self, fixed_range=None, num_networks=None,
network_size=None, vlan_start=None,
- vpn_start=None, fixed_range_v6=None, label='public'):
+ vpn_start=None, fixed_range_v6=None, label='public',
+ flat_network_bridge=None):
"""Creates fixed ips for host by range
arguments: [fixed_range=FLAG], [num_networks=FLAG],
[network_size=FLAG], [vlan_start=FLAG],
@@ -522,6 +523,8 @@ class NetworkCommands(object):
vpn_start = FLAGS.vpn_start
if not fixed_range_v6:
fixed_range_v6 = FLAGS.fixed_range_v6
+ if not flat_network_bridge:
+ flat_network_bridge = FLAGS.flat_network_bridge
net_manager = utils.import_object(FLAGS.network_manager)
net_manager.create_networks(context.get_admin_context(),
cidr=fixed_range,
@@ -530,7 +533,8 @@ class NetworkCommands(object):
vlan_start=int(vlan_start),
vpn_start=int(vpn_start),
cidr_v6=fixed_range_v6,
- label=label)
+ label=label,
+ flat_network_bridge)
def list(self):
"""List all created networks"""
diff --git a/nova/compute/api.py b/nova/compute/api.py
index c475e3bff..1737565aa 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -184,8 +184,7 @@ class API(base.Base):
instances = []
LOG.debug(_("Going to run %s instances..."), num_instances)
for num in range(num_instances):
- instance = dict(mac_address=utils.generate_mac(),
- launch_index=num,
+ instance = dict(launch_index=num,
**base_options)
instance = self.db.instance_create(context, instance)
instance_id = instance['id']
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index d659712ad..ce2fa8713 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -193,16 +193,22 @@ class ComputeManager(manager.Manager):
# with the address currently, but I'm leaving it as
# a call to ensure that network setup completes. We
# will eventually also need to save the address here.
+ #NOTE(tr3buchet): I don't see why we'd save it here when the network
+ # manager is saving it.
if not FLAGS.stub_network:
- address = rpc.call(context,
- self.get_network_topic(context),
- {"method": "allocate_fixed_ip",
+ rpc.call(context, self.get_network_topic(context),
+ {"method": "allocate_fixed_ips",
"args": {"instance_id": instance_id,
"vpn": is_vpn}})
+ rpc.call(context, self.get_network_topic(context),
+ {"method": "allocate_mac_addresses",
+ "args": {"instance_id": instance_id}})
self.network_manager.setup_compute_network(context,
instance_id)
+ Log.debug(_("instance addresses: |%s|"), instance_ref['fixed_ips'])
+
# TODO(vish) check to make sure the availability zone matches
self.db.instance_set_state(context,
instance_id,
diff --git a/nova/db/api.py b/nova/db/api.py
index dcaf55e8f..5b92afbcd 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -325,6 +325,37 @@ def fixed_ip_update(context, address, values):
####################
+def mac_address_create(context, values):
+ """create a new mac address record in teh database"""
+ return IMPL.mac_address_create(context, values)
+
+
+def mac_address_get(context, mac_address):
+ """gets a mac address from the table"""
+ return IMPL.mac_address_get(context, mac_address)
+
+
+def mac_address_get_all_by_instance(context, instance_id):
+ """gets all mac addresses for instance"""
+ return IMPL.mac_address_get_all_by_instance(context, instance_id)
+
+
+def mac_address_get_all_by_network(context, network_id):
+ """gets all mac addresses for instance"""
+ return IMPL.mac_address_get_all_by_network(context, network_id)
+
+
+def mac_address_delete(context, mac_address):
+ """delete mac address record in teh database"""
+ return IMPL.mac_address_delete(context, mac_address)
+
+
+def mac_address_delete_by_instance(context, instance_id):
+ """delete mac address record in teh database"""
+ return IMPL.mac_address_delete_by_instance(context, instance_id)
+####################
+
+
def instance_create(context, values):
"""Create an instance from the values dictionary."""
return IMPL.instance_create(context, values)
@@ -370,13 +401,13 @@ def instance_get_all_by_reservation(context, reservation_id):
return IMPL.instance_get_all_by_reservation(context, reservation_id)
-def instance_get_fixed_address(context, instance_id):
+def instance_get_fixed_addresses(context, instance_id):
"""Get the fixed ip address of an instance."""
- return IMPL.instance_get_fixed_address(context, instance_id)
+ return IMPL.instance_get_fixed_addresses(context, instance_id)
-def instance_get_fixed_address_v6(context, instance_id):
- return IMPL.instance_get_fixed_address_v6(context, instance_id)
+def instance_get_fixed_addresses_v6(context, instance_id):
+ return IMPL.instance_get_fixed_addresses_v6(context, instance_id)
def instance_get_floating_address(context, instance_id):
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 6df2a8843..6e59f4b1d 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -630,11 +630,16 @@ def fixed_ip_get_all_by_instance(context, instance_id):
@require_context
def fixed_ip_get_instance_v6(context, address):
session = get_session()
+
+ # convert IPv6 address to mac
mac = utils.to_mac(address)
+ # get mac address row
+ mac_ref = mac_address_get(context, mac)
+
+ # look up instance based on instance_id from mac address row
result = session.query(models.Instance).\
- filter_by(mac_address=mac).\
- first()
+ filter_by(id=mac_ref.instance_id)
return result
@@ -659,6 +664,98 @@ def fixed_ip_update(context, address, values):
@require_context
+def mac_address_create(context, values):
+ """create a new mac address record in teh database
+
+ context = request context object
+ values = dict containing column values
+ """
+ mac_address_ref = models.MacAddress()
+ mac_address_ref.update(values)
+ mac_address_ref.save()
+
+ session = get_session()
+ with session.begin():
+ instance = instance_get(context, instance_id, session=session)
+ network = network_get(context, network_id, session=session)
+ mac_address.instance = instance
+ mac_address.network = network
+ mac_address_ref.save(session=session)
+ return mac_address_ref
+
+
+def mac_address_get(context, mac_address):
+ """gets a mac address from the table
+
+ context = request context object
+ mac_address = the mac you're looking to get
+ """
+ session = get_session()
+ with session.begin():
+ mac_address_ref = session.query(models.MacAddress).\
+ filter_by(mac_address=mac_address)
+ return mac_address_ref
+
+
+@require_context
+def mac_address_get_all_by_instance(context, instance_id):
+ """gets all mac addresses for instance
+
+ context = request context object
+ instance_id = instance to retreive macs for
+ """
+ session = get_session()
+ with session.begin():
+ mac_address_refs = session.query(models.MacAddress).\
+ filter_by(instance_id=instance_id)
+ return mac_address_refs
+
+
+@require_context
+def mac_address_get_all_by_network(context, network_id):
+ """gets all mac addresses for instance
+
+ context = request context object
+ network_id = network to retreive macs for
+ """
+ session = get_session()
+ with session.begin():
+ mac_address_refs = session.query(models.MacAddress).\
+ filter_by(network_id=network_id)
+ return mac_address_refs
+
+
+@require_context
+def mac_address_delete(context, mac_address):
+ """delete mac address record in teh database
+
+ context = request context object
+ instance_id = instance to remove macs for
+ """
+ ref = mac_address_get(mac_address)
+ session = get_session()
+ with session.begin():
+ ref.delete(session=session)
+
+
+@require_context
+def mac_address_delete_by_instance(context, instance_id):
+ """delete mac address record in teh database
+
+ context = request context object
+ instance_id = instance to remove macs for
+ """
+ refs = mac_address_get_all_by_instance(instance_id)
+ session = get_session()
+ with session.begin():
+ for ref in refs:
+ ref.delete(session=session)
+
+
+###################
+
+
+@require_context
def instance_create(context, values):
"""Create a new Instance record in the database.
@@ -819,24 +916,35 @@ def instance_get_project_vpn(context, project_id):
@require_context
-def instance_get_fixed_address(context, instance_id):
+def instance_get_fixed_addresses(context, instance_id):
session = get_session()
with session.begin():
instance_ref = instance_get(context, instance_id, session=session)
- if not instance_ref.fixed_ip:
+ if not instance_ref.fixed_ips:
return None
- return instance_ref.fixed_ip['address']
+ return [fixed_ip.address for fixed_ip in instance_ref.fixed_ips]
@require_context
-def instance_get_fixed_address_v6(context, instance_id):
+def instance_get_fixed_addresses_v6(context, instance_id):
session = get_session()
with session.begin():
+ # get instance
instance_ref = instance_get(context, instance_id, session=session)
- network_ref = network_get_by_instance(context, instance_id)
- prefix = network_ref.cidr_v6
- mac = instance_ref.mac_address
- return utils.to_global_ipv6(prefix, mac)
+ # get networks associated with instance
+ network_refs = network_get_all_by_instance(context, instance_id)
+ # compile a list of cidr_v6 prefixes sorted by network id
+ prefixes = [ref.cidr_v6 for ref in
+ sorted(network_refs, key=lambda ref: ref.id)]
+ # get mac rows associated with instance
+ mac_refs = mac_address_get_all_by_instance(context, instance_ref.id)
+ # compile of list of the mac_addresses sorted by network id
+ macs = [ref.mac_address for ref in
+ sorted(mac_refs, key=lambda ref: ref.network_id)]
+ # combine prefixes and macs into (prefix,mac) pairs
+ prefix_mac_pairs = zip(prefixes, macs)
+ # return list containing ipv6 address for each pair
+ return [utils.to_global_ipv6(pair) for pair in prefix_mac_pairs]
@require_context
@@ -1081,7 +1189,8 @@ def network_get(context, network_id, session=None):
@require_admin_context
def network_get_all(context):
session = get_session()
- result = session.query(models.Network)
+ result = session.query(models.Network).\
+ filter_by(deleted=False)
if not result:
raise exception.NotFound(_('No networks defined'))
return result
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 1882efeba..bbadbeee4 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -174,7 +174,6 @@ class Instance(BASE, NovaBase):
user_data = Column(Text)
reservation_id = Column(String(255))
- mac_address = Column(String(255))
scheduled_at = Column(DateTime)
launched_at = Column(DateTime)
@@ -404,21 +403,6 @@ class Network(BASE, NovaBase):
host = Column(String(255)) # , ForeignKey('hosts.id'))
-class AuthToken(BASE, NovaBase):
- """Represents an authorization token for all API transactions.
-
- Fields are a string representing the actual token and a user id for
- mapping to the actual user
-
- """
- __tablename__ = 'auth_tokens'
- token_hash = Column(String(255), primary_key=True)
- user_id = Column(String(255))
- server_manageent_url = Column(String(255))
- storage_url = Column(String(255))
- cdn_management_url = Column(String(255))
-
-
# TODO(vish): can these both come from the same baseclass?
class FixedIp(BASE, NovaBase):
"""Represents a fixed ip for an instance."""
@@ -429,7 +413,7 @@ class FixedIp(BASE, NovaBase):
network = relationship(Network, backref=backref('fixed_ips'))
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
instance = relationship(Instance,
- backref=backref('fixed_ip', uselist=False),
+ backref=backref('fixed_ips'),
foreign_keys=instance_id,
primaryjoin='and_('
'FixedIp.instance_id == Instance.id,'
@@ -439,6 +423,48 @@ class FixedIp(BASE, NovaBase):
reserved = Column(Boolean, default=False)
+class FloatingIp(BASE, NovaBase):
+ """Represents a floating ip that dynamically forwards to a fixed ip."""
+ __tablename__ = 'floating_ips'
+ id = Column(Integer, primary_key=True)
+ address = Column(String(255))
+ fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True)
+ fixed_ip = relationship(FixedIp,
+ backref=backref('floating_ips'),
+ foreign_keys=fixed_ip_id,
+ primaryjoin='and_('
+ 'FloatingIp.fixed_ip_id == FixedIp.id,'
+ 'FloatingIp.deleted == False)')
+ project_id = Column(String(255))
+ host = Column(String(255)) # , ForeignKey('hosts.id'))
+
+
+class MacAddress(BASE, NovaBase):
+ """Represents a mac address used by an instance"""
+ __tablename__ = 'mac_addresses'
+ id = Column(Integer, primary_key=True)
+ mac_address = Column(String(255), unique=True)
+ network_id = Column(Integer, ForeignKey('networks.id'), nullable=False)
+ network = relationship(Network, backref=backref('mac_addresses'))
+ instance_id = Column(Integer, ForeignKey('instances.id'), nullable=False)
+ instance = relationship(Instance, backref=backref('mac_addresses'))
+
+
+class AuthToken(BASE, NovaBase):
+ """Represents an authorization token for all API transactions.
+
+ Fields are a string representing the actual token and a user id for
+ mapping to the actual user
+
+ """
+ __tablename__ = 'auth_tokens'
+ token_hash = Column(String(255), primary_key=True)
+ user_id = Column(String(255))
+ server_manageent_url = Column(String(255))
+ storage_url = Column(String(255))
+ cdn_management_url = Column(String(255))
+
+
class User(BASE, NovaBase):
"""Represents a user."""
__tablename__ = 'users'
@@ -499,22 +525,6 @@ class UserProjectAssociation(BASE, NovaBase):
project_id = Column(String(255), ForeignKey(Project.id), primary_key=True)
-class FloatingIp(BASE, NovaBase):
- """Represents a floating ip that dynamically forwards to a fixed ip."""
- __tablename__ = 'floating_ips'
- id = Column(Integer, primary_key=True)
- address = Column(String(255))
- fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True)
- fixed_ip = relationship(FixedIp,
- backref=backref('floating_ips'),
- foreign_keys=fixed_ip_id,
- primaryjoin='and_('
- 'FloatingIp.fixed_ip_id == FixedIp.id,'
- 'FloatingIp.deleted == False)')
- project_id = Column(String(255))
- host = Column(String(255)) # , ForeignKey('hosts.id'))
-
-
class ConsolePool(BASE, NovaBase):
"""Represents pool of consoles on the same physical node."""
__tablename__ = 'console_pools'
diff --git a/nova/exception.py b/nova/exception.py
index 7d65bd6a5..95580ebea 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -123,3 +123,7 @@ def wrap_exception(f):
raise
_wrap.func_name = f.func_name
return _wrap
+
+
+class MacAddress(Error):
+ pass
diff --git a/nova/network/api.py b/nova/network/api.py
index bf43acb51..c46d600ca 100644
--- a/nova/network/api.py
+++ b/nova/network/api.py
@@ -85,3 +85,9 @@ class API(base.Base):
self.db.queue_get_for(context, FLAGS.network_topic, host),
{"method": "disassociate_floating_ip",
"args": {"floating_address": floating_ip['address']}})
+
+ def get_instance_network_info(self, context, instance_id):
+ """return the network info for an instance"""
+ return rpc.call(context, FLAGS.network_topic,
+ {"method": "get_instance_network_info",
+ "args": {"instance_id": instance_id}})
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 12a0c5018..fba8b405a 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -293,6 +293,20 @@ class NetworkManager(manager.Manager):
'address': address,
'reserved': reserved})
+ def generate_mac_address(self):
+ """generate a mac address for a vif on an instance"""
+ mac = [0x02, 0x16, 0x3e,
+ random.randint(0x00, 0x7f),
+ random.randint(0x00, 0xff),
+ random.randint(0x00, 0xff)]
+ return ':'.join(map(lambda x: "%02x" % x, mac))
+
+
+# def setup_new_instance(self, context, instance_id, host):
+# """allocate the network config for a new instance on host"""
+# for network in DB_NETWORKGETALLBYHOST():
+# ip = self.allocate_fixed_ip(context, instance_id, network)
+
class FlatManager(NetworkManager):
"""Basic network where no vlans are used.
@@ -332,31 +346,48 @@ class FlatManager(NetworkManager):
for network in self.db.host_get_networks(ctxt, self.host):
self._on_set_network_host(ctxt, network['id'])
- def allocate_fixed_ip(self, context, instance_id, *args, **kwargs):
- """Gets a fixed ip from the pool."""
+ def allocate_mac_addresses(self, context, instance_id):
+ """generates and stores mac addresses"""
+ mac_address = {'mac_address': self.generate_mac_address(),
+ 'instance_id': instance_id,
+ 'network_id': network.id}
+
+ networks = self.db.network_get_all(context)
+ for network in networks:
+ for i in range(5):
+ try:
+ mac_address['mac_address'] = self.generate_mac_address(),
+ self.db.mac_address_create(context, row)
+ break
+ except:
+ #TODO(tr3buchet) find this exception
+ pass
+ else:
+ self.db.mac_address_delete(context, instance_id=instance_id)
+ raise exception.MacAddress(_("5 attempts at create failed"))
+
+ def allocate_fixed_ips(self, context, instance_id, *args, **kwargs):
+ """Gets a fixed ip from a host's pool."""
# TODO(vish): when this is called by compute, we can associate compute
# with a network, or a cluster of computes with a network
# and use that network here with a method like
# network_get_by_compute_host
- network_ref = self.db.network_get_by_bridge(context,
- FLAGS.flat_network_bridge)
- address = self.db.fixed_ip_associate_pool(context.elevated(),
- network_ref['id'],
- instance_id)
- self.db.fixed_ip_update(context, address, {'allocated': True})
- return address
+ networks = self.db.network_get_all(context)
+# network_ref = self.db.network_get_by_bridge(context,
+# FLAGS.flat_network_bridge)
+ for network in networks:
+ address = self.db.fixed_ip_associate_pool(context.elevated(),
+ network.id,
+ instance_id)
+ self.db.fixed_ip_update(context, address, {'allocated': True})
def deallocate_fixed_ip(self, context, address, *args, **kwargs):
"""Returns a fixed ip to the pool."""
self.db.fixed_ip_update(context, address, {'allocated': False})
self.db.fixed_ip_disassociate(context.elevated(), address)
- def setup_compute_network(self, context, instance_id):
- """Network is created manually."""
- pass
-
def create_networks(self, context, cidr, num_networks, network_size,
- cidr_v6, label, *args, **kwargs):
+ cidr_v6, label, bridge, *args, **kwargs):
"""Create networks based on parameters."""
fixed_net = IPy.IP(cidr)
fixed_net_v6 = IPy.IP(cidr_v6)
@@ -368,7 +399,7 @@ class FlatManager(NetworkManager):
cidr = "%s/%s" % (fixed_net[start], significant_bits)
project_net = IPy.IP(cidr)
net = {}
- net['bridge'] = FLAGS.flat_network_bridge
+ net['bridge'] = bridge
net['dns'] = FLAGS.flat_network_dns
net['cidr'] = cidr
net['netmask'] = str(project_net.netmask())
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index b049ac943..ba1f6be46 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -65,7 +65,6 @@ class ComputeTestCase(test.TestCase):
inst['user_id'] = self.user.id
inst['project_id'] = self.project.id
inst['instance_type'] = 'm1.tiny'
- inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = 0
return db.instance_create(self.context, inst)['id']
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index 1e42fddf3..b1e7910ca 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -63,7 +63,6 @@ class QuotaTestCase(test.TestCase):
inst['project_id'] = self.project.id
inst['instance_type'] = 'm1.large'
inst['vcpus'] = cores
- inst['mac_address'] = utils.generate_mac()
return db.instance_create(self.context, inst)['id']
def _create_volume(self, size=10):
diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py
index b6888c4d2..b34b374fd 100644
--- a/nova/tests/test_scheduler.py
+++ b/nova/tests/test_scheduler.py
@@ -160,7 +160,6 @@ class SimpleDriverTestCase(test.TestCase):
inst['user_id'] = self.user.id
inst['project_id'] = self.project.id
inst['instance_type'] = 'm1.tiny'
- inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = 0
inst['vcpus'] = 1
inst['availability_zone'] = kwargs.get('availability_zone', None)
diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
index b40ca004b..68412a184 100644
--- a/nova/tests/test_volume.py
+++ b/nova/tests/test_volume.py
@@ -105,7 +105,6 @@ class VolumeTestCase(test.TestCase):
inst['user_id'] = 'fake'
inst['project_id'] = 'fake'
inst['instance_type'] = 'm1.tiny'
- inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = 0
instance_id = db.instance_create(self.context, inst)['id']
mountpoint = "/dev/sdf"
diff --git a/nova/utils.py b/nova/utils.py
index 0cf91e0cc..415976f44 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -231,14 +231,6 @@ def generate_uid(topic, size=8):
return '%s-%s' % (topic, ''.join(choices))
-def generate_mac():
- mac = [0x02, 0x16, 0x3e,
- random.randint(0x00, 0x7f),
- random.randint(0x00, 0xff),
- random.randint(0x00, 0xff)]
- return ':'.join(map(lambda x: "%02x" % x, mac))
-
-
def generate_password(length=20):
"""Generate a random sequence of letters and digits
to be used as a password. Note that this is not intended