From 089bdfa8c2f0f116b55c69bbcde6fca6632cb145 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 15:20:23 -0600 Subject: should be writing some kindof network info to the xenstore now, hopefully --- nova/db/api.py | 5 +++++ nova/db/sqlalchemy/api.py | 6 ++++++ nova/db/sqlalchemy/models.py | 1 + nova/virt/xenapi/vmops.py | 39 +++++++++++++++++++++++++++++++-------- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/nova/db/api.py b/nova/db/api.py index f9d561587..7b37bce2f 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -501,6 +501,11 @@ def network_get(context, network_id): return IMPL.network_get(context, network_id) +def network_get_all(context): + """Get all networks""" + returm IMPL.network_get_all(context) + + # pylint: disable-msg=C0103 def network_get_associated_fixed_ips(context, network_id): """Get all network's ips that have been associated.""" diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index b63b84bed..053780158 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1054,6 +1054,12 @@ def network_get(context, network_id, session=None): return result +@require_context +def network_get_all(context): + session = get_session() + return session.query(models.Network).all() + + # NOTE(vish): pylint complains because of the long method name, but # it fits with the names of the rest of the methods # pylint: disable-msg=C0103 diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index c54ebe3ba..dc476acf4 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -369,6 +369,7 @@ class Network(BASE, NovaBase): "vpn_public_port"), {'mysql_engine': 'InnoDB'}) id = Column(Integer, primary_key=True) + label = Column(String(255)) injected = Column(Boolean, default=False) cidr = Column(String(255), unique=True) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 6c2fd6a68..882b9d9d6 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -67,11 +67,6 @@ class VMOps(object): raise exception.Duplicate(_('Attempted to create' ' non-unique name %s') % instance.name) - bridge = db.network_get_by_instance(context.get_admin_context(), - instance['id'])['bridge'] - network_ref = \ - NetworkHelper.find_network_with_bridge(self._session, bridge) - user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) #if kernel is not present we must download a raw disk @@ -99,9 +94,29 @@ class VMOps(object): instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) - if network_ref: - VMHelper.create_vif(self._session, vm_ref, - network_ref, instance.mac_address) + # write network info + network = db.network_get_by_instance(context.get_admin_context(), + instance['id']) + for network in db.network_get_all(): + mapping = {'label': network['label'], + 'gateway': network['gateway'], + 'mac': instance.mac_address, + 'dns': network['dns'], + 'ips': [{'netmask': network['netmask'], + 'enabled': '1', + 'ip': 192.168.3.3}]} # <===== CHANGE!!!! + self.write_network_config_to_xenstore(vm_ref, mapping) + + bridge = network['bridge'] + network_ref = \ + NetworkHelper.find_network_with_bridge(self._session, bridge) + + if network_ref: + VMHelper.create_vif(self._session, vm_ref, + network_ref, instance.mac_address) + + # call reset networking + LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) LOG.info(_('Spawning VM %s created %s.'), instance.name, vm_ref) @@ -341,6 +356,14 @@ class VMOps(object): # TODO: implement this! return 'http://fakeajaxconsole/fake_url' + def reset_networking(self, instance): + vm = self._get_vm_opaque_ref(instance) + self.write_to_xenstore(vm, "resetnetwork", "") + + def write_network_config_to_xenstore(self, instance): + vm = self._get_vm_opaque_ref(instance) + self.write_to_param_xenstore(vm, mapping) + def list_from_xenstore(self, vm, path): """Runs the xenstore-ls command to get a listing of all records from 'path' downward. Returns a dict with the sub-paths as keys, -- cgit From 9b993d50835c79d23dca422335de362ebaf7f4fa Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 15:47:08 -0600 Subject: added plugin call for resetnetworking --- nova/virt/xenapi/vmops.py | 3 ++- plugins/xenserver/xenapi/etc/xapi.d/plugins/agent | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 882b9d9d6..7f9e78df5 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -358,7 +358,8 @@ class VMOps(object): def reset_networking(self, instance): vm = self._get_vm_opaque_ref(instance) - self.write_to_xenstore(vm, "resetnetwork", "") + args = {'id': str(uuid.uuid4())} + resp = self._make_agent_call('resetnetwork', vm, '', args) def write_network_config_to_xenstore(self, instance): vm = self._get_vm_opaque_ref(instance) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index 12c3a19c8..5c5ec7c45 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -91,6 +91,18 @@ def password(self, arg_dict): return resp +@jsonify +def resetnetwork(self, arg_dict): + """ + writes a resquest to xenstore that tells the agent to reset the networking + + """ + arg_dict['value'] = json.dumps({'name': 'resetnetwork', 'value': ''}) + request_id = arg_dict['id'] + arg_dict['path'] = "data/host/%s" % request_id + xenstore.write_record(self, arg_dict) + + def _wait_for_agent(self, request_id, arg_dict): """Periodically checks xenstore for a response from the agent. The request is always written to 'data/host/{id}', and -- cgit From 8d1798008fcec536f1117a275b168ca449f1dfbf Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 16:19:07 -0600 Subject: syntax error --- nova/db/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/api.py b/nova/db/api.py index 7b37bce2f..f22cd5615 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -503,7 +503,7 @@ def network_get(context, network_id): def network_get_all(context): """Get all networks""" - returm IMPL.network_get_all(context) + return IMPL.network_get_all(context) # pylint: disable-msg=C0103 -- cgit From f77043d44aa640e1811a3fe236fc8fd5dfecf990 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 16:27:09 -0600 Subject: syntax --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 7f9e78df5..1045d5d98 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -104,7 +104,7 @@ class VMOps(object): 'dns': network['dns'], 'ips': [{'netmask': network['netmask'], 'enabled': '1', - 'ip': 192.168.3.3}]} # <===== CHANGE!!!! + 'ip': '192.168.3.3'}]} # <===== CHANGE!!!! self.write_network_config_to_xenstore(vm_ref, mapping) bridge = network['bridge'] -- cgit From f38196b0eb7a11501f9b0ffa9409c05510798761 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 18:08:01 -0600 Subject: added default label to nova-manage and create_networks --- bin/nova-manage | 5 +++-- nova/network/manager.py | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index d0901ddfc..38d36ab0f 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -442,7 +442,7 @@ 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): + fixed_range_v6=None, label='public'): """Creates fixed ips for host by range arguments: [fixed_range=FLAG], [num_networks=FLAG], [network_size=FLAG], [vlan_start=FLAG], @@ -463,7 +463,8 @@ class NetworkCommands(object): net_manager.create_networks(context.get_admin_context(), fixed_range, int(num_networks), int(network_size), int(vlan_start), - int(vpn_start), fixed_range_v6) + int(vpn_start), fixed_range_v6, + label) class ServiceCommands(object): diff --git a/nova/network/manager.py b/nova/network/manager.py index 61de8055a..a377c40c6 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -325,11 +325,12 @@ class FlatManager(NetworkManager): pass def create_networks(self, context, cidr, num_networks, network_size, - cidr_v6, *args, **kwargs): + cidr_v6, label, *args, **kwargs): """Create networks based on parameters.""" fixed_net = IPy.IP(cidr) fixed_net_v6 = IPy.IP(cidr_v6) significant_bits_v6 = 64 + count = 1 for index in range(num_networks): start = index * network_size significant_bits = 32 - int(math.log(network_size, 2)) @@ -342,6 +343,11 @@ class FlatManager(NetworkManager): net['gateway'] = str(project_net[1]) net['broadcast'] = str(project_net.broadcast()) net['dhcp_start'] = str(project_net[2]) + if num_networks > 1: + net['label'] = "%s_%d" % (label, count) + else: + net['label'] = label + count += 1 if(FLAGS.use_ipv6): cidr_v6 = "%s/%s" % (fixed_net_v6[0], significant_bits_v6) -- cgit From a9f9a0fcb7443b93db3f4de8f68218f20f0cc1a9 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 18:36:18 -0600 Subject: really added migration for networks label --- .../sqlalchemy/migrate_repo/versions/003_cactus.py | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py new file mode 100644 index 000000000..13b4766d8 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py @@ -0,0 +1,47 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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 log as logging + + +meta = MetaData() + + +# +# New Tables +# + + +# +# Tables to alter +# + +networks_label = Column( + 'label', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + networks.create_column(networks_label) -- cgit From d4a643976adbe49ec52db53694481e9ba687cddf Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 18:40:04 -0600 Subject: fixed the migration --- nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py index 13b4766d8..ddfe114cb 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py @@ -25,6 +25,11 @@ from nova import log as logging meta = MetaData() +networks = Table('networks', meta, + Column('id', Integer(), primary_key=True, nullable=False), + ) + + # # New Tables # -- cgit From 7ef1c34c2251eb32ef2effa58ea7ee85f46112f7 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 18:44:00 -0600 Subject: moved argument for label --- bin/nova-manage | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 38d36ab0f..73832b0eb 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -441,8 +441,8 @@ class NetworkCommands(object): """Class for managing networks.""" def create(self, fixed_range=None, num_networks=None, - network_size=None, vlan_start=None, vpn_start=None, - fixed_range_v6=None, label='public'): + network_size=None, label='public', vlan_start=None, + vpn_start=None, fixed_range_v6=None): """Creates fixed ips for host by range arguments: [fixed_range=FLAG], [num_networks=FLAG], [network_size=FLAG], [vlan_start=FLAG], -- cgit From 00b029f60baca843487b3cfd89940ed65e85389a Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 20 Jan 2011 18:51:46 -0600 Subject: undid moving argument --- bin/nova-manage | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 73832b0eb..9603c6a49 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -441,8 +441,8 @@ class NetworkCommands(object): """Class for managing networks.""" def create(self, fixed_range=None, num_networks=None, - network_size=None, label='public', vlan_start=None, - vpn_start=None, fixed_range_v6=None): + network_size=None, vlan_start=None, + vpn_start=None, fixed_range_v6=None, label='public'): """Creates fixed ips for host by range arguments: [fixed_range=FLAG], [num_networks=FLAG], [network_size=FLAG], [vlan_start=FLAG], -- cgit From 0c7893e4119bcccdfdfdcdef0931fcc8802688e8 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Wed, 26 Jan 2011 14:59:17 -0600 Subject: added mapping parameter to write_network_config_to_xenstore --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index c7310987b..68fa1ecd6 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -391,7 +391,7 @@ class VMOps(object): args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', vm, '', args) - def write_network_config_to_xenstore(self, instance): + def write_network_config_to_xenstore(self, instance, mapping): vm = self._get_vm_opaque_ref(instance) self.write_to_param_xenstore(vm, mapping) -- cgit From eabc4c00eea8859c37efed3f180edbc41fd3b71d Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 27 Jan 2011 23:53:28 -0600 Subject: Working on api / manager / db support for zones --- bin/nova-manage | 10 ++++++++++ nova/api/openstack/__init__.py | 5 +++++ nova/db/api.py | 8 ++++++++ nova/db/sqlalchemy/api.py | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index 7835ca551..b62687aec 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -569,6 +569,15 @@ class DbCommands(object): print migration.db_version() +class ZoneCommands(object): + """Methods for defining zones.""" + + def create(self, name): + """Create a new Zone for this deployment.""" + ctxt = context.get_admin_context() + db.create_zone(ctxt, name) + + class VolumeCommands(object): """Methods for dealing with a cloud in an odd state""" @@ -620,6 +629,7 @@ CATEGORIES = [ ('service', ServiceCommands), ('log', LogCommands), ('db', DbCommands), + ('zone', ZoneCommands), ('volume', VolumeCommands)] diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c70bb39ed..025fa12a4 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -34,6 +34,7 @@ from nova.api.openstack import flavors from nova.api.openstack import images from nova.api.openstack import servers from nova.api.openstack import shared_ip_groups +from nova.api.openstack import zones LOG = logging.getLogger('nova.api.openstack') @@ -79,6 +80,10 @@ class APIRouter(wsgi.Router): server_members["actions"] = "GET" server_members['suspend'] = 'POST' server_members['resume'] = 'POST' + + mapper.resource("zone", "zones", controller=zones.Controller(), + collection={'detail': 'GET'}, + member=zone_members) mapper.resource("server", "servers", controller=servers.Controller(), collection={'detail': 'GET'}, diff --git a/nova/db/api.py b/nova/db/api.py index 789cb8ebb..dc35f20b2 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -980,3 +980,11 @@ def console_get_all_by_instance(context, instance_id): def console_get(context, console_id, instance_id=None): """Get a specific console (possibly on a given instance).""" return IMPL.console_get(context, console_id, instance_id) + + +#################### + + +def create_zone(context, name): + """Create a new Zone entry for this deployment.""" + return IMPL.create_zone(context, name) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 895e7eabe..ec36c481e 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1996,3 +1996,12 @@ def console_get(context, console_id, instance_id=None): raise exception.NotFound(_("No console with id %(console_id)s" " %(idesc)s") % locals()) return result + + +################## + + +@require_admin_context +def create_zone(context, zone): + session = get_session() + print "Creating Zone", zone -- cgit From 620eba09a96f25a059249c23a5e73efd18aaf89a Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 1 Feb 2011 14:11:21 -0600 Subject: forgot context param for network_get_all --- nova/virt/xenapi/vmops.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 68fa1ecd6..da2e5c672 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -95,9 +95,10 @@ class VMOps(object): VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) # write network info - network = db.network_get_by_instance(context.get_admin_context(), + admin_context = context.get_admin_context() + network = db.network_get_by_instance(admin_context, instance['id']) - for network in db.network_get_all(): + for network in db.network_get_all(admin_context): mapping = {'label': network['label'], 'gateway': network['gateway'], 'mac': instance.mac_address, -- cgit From 0e6b1c02b3ae82526f3cf83ce70213e7a107701d Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 1 Feb 2011 15:41:53 -0600 Subject: added to inject networking data into the xenstore --- nova/virt/xenapi/vmops.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index da2e5c672..6edeae5c0 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -99,14 +99,16 @@ class VMOps(object): network = db.network_get_by_instance(admin_context, instance['id']) for network in db.network_get_all(admin_context): + mac_id = instance.mac_address.replace(':', '') + location = 'vm-data/networking/%s' % mac_id mapping = {'label': network['label'], 'gateway': network['gateway'], 'mac': instance.mac_address, - 'dns': network['dns'], + 'dns': [network['dns']], 'ips': [{'netmask': network['netmask'], 'enabled': '1', 'ip': '192.168.3.3'}]} # <===== CHANGE!!!! - self.write_network_config_to_xenstore(vm_ref, mapping) + self.write_to_param_xenstore(vm_ref, {location: mapping}) bridge = network['bridge'] network_ref = \ @@ -392,10 +394,6 @@ class VMOps(object): args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', vm, '', args) - def write_network_config_to_xenstore(self, instance, mapping): - vm = self._get_vm_opaque_ref(instance) - self.write_to_param_xenstore(vm, mapping) - def list_from_xenstore(self, vm, path): """Runs the xenstore-ls command to get a listing of all records from 'path' downward. Returns a dict with the sub-paths as keys, -- cgit From 41e615b843c284631a0d878db2c93ef97f2eb4b8 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 7 Feb 2011 14:46:54 -0400 Subject: minor --- nova/api/openstack/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 025fa12a4..8901a8987 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -83,7 +83,7 @@ class APIRouter(wsgi.Router): mapper.resource("zone", "zones", controller=zones.Controller(), collection={'detail': 'GET'}, - member=zone_members) + collection_name='zones') mapper.resource("server", "servers", controller=servers.Controller(), collection={'detail': 'GET'}, -- cgit From b6022c1f7d7dc9294f6b1b613c7e99bd9437a72e Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Mon, 7 Feb 2011 13:43:23 -0600 Subject: added network_get_all_by_instance(), call to reset_network in vmops --- nova/db/sqlalchemy/api.py | 19 +++++++++++++------ nova/virt/xenapi/vmops.py | 11 +++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 31865d553..26b685e43 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1055,12 +1055,6 @@ def network_get(context, network_id, session=None): return result -@require_context -def network_get_all(context): - session = get_session() - return session.query(models.Network).all() - - # NOTE(vish): pylint complains because of the long method name, but # it fits with the names of the rest of the methods # pylint: disable-msg=C0103 @@ -1104,6 +1098,19 @@ def network_get_by_instance(_context, instance_id): return rv +@require_admin_context +def network_get_all_by_instance(_context, instance_id): + session = get_session() + rv = session.query(models.Network).\ + filter_by(deleted=False).\ + join(models.Network.fixed_ips).\ + filter_by(instance_id=instance_id).\ + filter_by(deleted=False) + if not rv: + raise exception.NotFound(_('No network for instance %s') % instance_id) + return rv + + @require_admin_context def network_set_host(context, network_id, host_id): session = get_session() diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 6edeae5c0..4056e99bc 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -96,9 +96,11 @@ class VMOps(object): # write network info admin_context = context.get_admin_context() - network = db.network_get_by_instance(admin_context, - instance['id']) - for network in db.network_get_all(admin_context): + #network = db.network_get_by_instance(admin_context, + # instance['id']) + + for network in db.network_get_all_by_instance(admin_context, + instance['id']): mac_id = instance.mac_address.replace(':', '') location = 'vm-data/networking/%s' % mac_id mapping = {'label': network['label'], @@ -119,6 +121,7 @@ class VMOps(object): network_ref, instance.mac_address) # call reset networking + self.reset_network(vm_ref) LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) @@ -389,7 +392,7 @@ class VMOps(object): # TODO: implement this! return 'http://fakeajaxconsole/fake_url' - def reset_networking(self, instance): + def reset_network(self, instance): vm = self._get_vm_opaque_ref(instance) args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', vm, '', args) -- cgit From 6e881239c9b8a1fb209868addf1a2b83042f2128 Mon Sep 17 00:00:00 2001 From: brian-lamar Date: Wed, 9 Feb 2011 13:30:40 -0500 Subject: 1) Moved tests for limiter to test_common.py (from __init__.py) and expanded test suite to include bad inputs and tests for custom limits (#2) 2) Wrapped int() calls in blocks to ensure logic regardless of input. 3) Moved 1000 hard limit hard-coding to a keyword param. 4) Added comments as I went. --- nova/api/openstack/common.py | 33 ++++--- nova/tests/api/openstack/__init__.py | 28 ------ nova/tests/api/openstack/test_common.py | 161 ++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 41 deletions(-) create mode 100644 nova/tests/api/openstack/test_common.py diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 6d2fa16e8..1dc3767e2 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -18,22 +18,29 @@ from nova import exception -def limited(items, req): - """Return a slice of items according to requested offset and limit. - - items - a sliceable - req - wobob.Request possibly containing offset and limit GET variables. - offset is where to start in the list, and limit is the maximum number - of items to return. +def limited(items, request, max_limit=1000): + """ + Return a slice of items according to requested offset and limit. - If limit is not specified, 0, or > 1000, defaults to 1000. + @param items: A sliceable entity + @param request: `webob.Request` possibly containing 'offset' and 'limit' + GET variables. 'offset' is where to start in the list, + and 'limit' is the maximum number of items to return. If + 'limit' is not specified, 0, or > max_limit, we default + to max_limit. + @kwarg max_limit: The maximum number of items to return from 'items' """ + try: + offset = int(request.GET.get('offset', 0)) + except ValueError: + offset = 0 + + try: + limit = int(request.GET.get('limit', max_limit)) + except ValueError: + limit = max_limit - offset = int(req.GET.get('offset', 0)) - limit = int(req.GET.get('limit', 0)) - if not limit: - limit = 1000 - limit = min(1000, limit) + limit = min(max_limit, limit or max_limit) range_end = offset + limit return items[offset:range_end] diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index 14eaaa62c..77b1dd37f 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -92,31 +92,3 @@ class RateLimitingMiddlewareTest(unittest.TestCase): self.assertEqual(middleware.limiter.__class__.__name__, "Limiter") middleware = RateLimitingMiddleware(simple_wsgi, service_host='foobar') self.assertEqual(middleware.limiter.__class__.__name__, "WSGIAppProxy") - - -class LimiterTest(unittest.TestCase): - - def test_limiter(self): - items = range(2000) - req = Request.blank('/') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=0') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=3') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=2005') - self.assertEqual(limited(items, req), []) - req = Request.blank('/?limit=10') - self.assertEqual(limited(items, req), items[:10]) - req = Request.blank('/?limit=0') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?limit=3000') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=1&limit=3') - self.assertEqual(limited(items, req), items[1:4]) - req = Request.blank('/?offset=3&limit=0') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=3&limit=1500') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=3000&limit=10') - self.assertEqual(limited(items, req), []) diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py new file mode 100644 index 000000000..9d9837cc9 --- /dev/null +++ b/nova/tests/api/openstack/test_common.py @@ -0,0 +1,161 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 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. + +""" +Test suites for 'common' code used throughout the OpenStack HTTP API. +""" + +import unittest + +from webob import Request + +from nova.api.openstack.common import limited + + +class LimiterTest(unittest.TestCase): + """ + Unit tests for the `nova.api.openstack.common.limited` method which takes + in a list of items and, depending on the 'offset' and 'limit' GET params, + returns a subset or complete set of the given items. + """ + + def setUp(self): + """ + Run before each test. + """ + self.tiny = range(1) + self.small = range(10) + self.medium = range(1000) + self.large = range(10000) + + def test_limiter_offset_zero(self): + """ + Test offset key works with 0. + """ + req = Request.blank('/?offset=0') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_offset_medium(self): + """ + Test offset key works with a medium sized number. + """ + req = Request.blank('/?offset=10') + self.assertEqual(limited(self.tiny, req), []) + self.assertEqual(limited(self.small, req), self.small[10:]) + self.assertEqual(limited(self.medium, req), self.medium[10:]) + self.assertEqual(limited(self.large, req), self.large[10:1010]) + + def test_limiter_offset_over_max(self): + """ + Test offset key works with a number over 1000 (max_limit). + """ + req = Request.blank('/?offset=1001') + self.assertEqual(limited(self.tiny, req), []) + self.assertEqual(limited(self.small, req), []) + self.assertEqual(limited(self.medium, req), []) + self.assertEqual(limited(self.large, req), self.large[1001:2001]) + + def test_limiter_offset_blank(self): + """ + Test offset key works with a blank offset. + """ + req = Request.blank('/?offset=') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_offset_bad(self): + """ + Test offset key works with a BAD offset. + """ + req = Request.blank(u'/?offset=\u0020aa') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_nothing(self): + """ + Test request with no offset or limit + """ + req = Request.blank('/') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_zero(self): + """ + Test limit of zero. + """ + req = Request.blank('/?limit=0') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_medium(self): + """ + Test limit of 10. + """ + req = Request.blank('/?limit=10') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium[:10]) + self.assertEqual(limited(self.large, req), self.large[:10]) + + def test_limiter_limit_over_max(self): + """ + Test limit of 3000. + """ + req = Request.blank('/?limit=3000') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_and_offset(self): + """ + Test request with both limit and offset. + """ + items = range(2000) + req = Request.blank('/?offset=1&limit=3') + self.assertEqual(limited(items, req), items[1:4]) + req = Request.blank('/?offset=3&limit=0') + self.assertEqual(limited(items, req), items[3:1003]) + req = Request.blank('/?offset=3&limit=1500') + self.assertEqual(limited(items, req), items[3:1003]) + req = Request.blank('/?offset=3000&limit=10') + self.assertEqual(limited(items, req), []) + + def test_limiter_custom_max_limit(self): + """ + Test a max_limit other than 1000. + """ + items = range(2000) + req = Request.blank('/?offset=1&limit=3') + self.assertEqual(limited(items, req, max_limit=2000), items[1:4]) + req = Request.blank('/?offset=3&limit=0') + self.assertEqual(limited(items, req, max_limit=2000), items[3:]) + req = Request.blank('/?offset=3&limit=2500') + self.assertEqual(limited(items, req, max_limit=2000), items[3:]) + req = Request.blank('/?offset=3000&limit=10') + self.assertEqual(limited(items, req, max_limit=2000), []) -- cgit From 590f5f1793c1f829101b4edbacbc79eac7acd2ef Mon Sep 17 00:00:00 2001 From: brian-lamar Date: Wed, 9 Feb 2011 13:36:16 -0500 Subject: Added myself to Authors --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 27782738f..14cc95377 100644 --- a/Authors +++ b/Authors @@ -3,6 +3,7 @@ Anne Gentle Anthony Young Antony Messerli Armando Migliaccio +Brian Lamar Chiradeep Vittal Chmouel Boudjnah Chris Behrens -- cgit From 52e1ad5321590b7b4671349373217bc8fce275fc Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 9 Feb 2011 15:55:29 -0500 Subject: - population of public and private addresses containers in openstack api - replacement of sqlalchemy model in instance stub with dict --- nova/api/openstack/servers.py | 18 +++++++++ nova/tests/api/openstack/test_servers.py | 66 ++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 17c5519a1..60f3d96e3 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -64,6 +64,24 @@ def _translate_detail_keys(inst): inst_dict['status'] = power_mapping[inst_dict['status']] inst_dict['addresses'] = dict(public=[], private=[]) + + # grab single private fixed ip + try: + private_ip = inst['fixed_ip']['address'] + if private_ip: + inst_dict['addresses']['private'].append(private_ip) + except KeyError: + LOG.debug(_("Failed to read private ip")) + pass + + # grab all public floating ips + try: + [inst_dict['addresses']['public'].append(floating['address']) \ + for floating in inst['fixed_ip']['floating_ips']] + except KeyError: + LOG.debug(_("Failed to read public ip(s)")) + pass + inst_dict['metadata'] = {} inst_dict['hostId'] = '' diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 724f14f19..816a0ab8c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -17,6 +17,7 @@ import json import unittest +import datetime import stubout import webob @@ -39,6 +40,13 @@ def return_server(context, id): return stub_instance(id) +def return_server_with_addresses(private, public): + def _return_server(context, id): + return stub_instance(id, private_address=private, + public_addresses=public) + return _return_server + + def return_servers(context, user_id=1): return [stub_instance(i, user_id) for i in xrange(5)] @@ -55,9 +63,45 @@ def instance_address(context, instance_id): return None -def stub_instance(id, user_id=1): - return Instance(id=id, state=0, image_id=10, user_id=user_id, - display_name='server%s' % id) +def stub_instance(id, user_id=1, private_address=None, public_addresses=None): + if public_addresses == None: + public_addresses = list() + + instance = { + "id": id, + "admin_pass": "", + "user_id": user_id, + "project_id": "", + "image_id": 10, + "kernel_id": "", + "ramdisk_id": "", + "launch_index": 0, + "key_name": "", + "key_data": "", + "state": 0, + "state_description": "", + "memory_mb": 0, + "vcpus": 0, + "local_gb": 0, + "hostname": "", + "host": "", + "instance_type": "", + "user_data": "", + "reservation_id": "", + "mac_address": "", + "scheduled_at": datetime.datetime.now(), + "launched_at": datetime.datetime.now(), + "terminated_at": datetime.datetime.now(), + "availability_zone": "", + "display_name": "server%s" % id, + "display_description": "", + "locked": False} + + instance["fixed_ip"] = { + "address": private_address, + "floating_ips": [{"address":ip} for ip in public_addresses]} + + return instance def fake_compute_api(cls, req, id): @@ -105,6 +149,22 @@ class ServersTest(unittest.TestCase): self.assertEqual(res_dict['server']['id'], '1') self.assertEqual(res_dict['server']['name'], 'server1') + def test_get_server_by_id_with_addresses(self): + private = "192.168.0.3" + public = ["1.2.3.4"] + new_return_server = return_server_with_addresses(private, public) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + req = webob.Request.blank('/v1.0/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['name'], 'server1') + addresses = res_dict['server']['addresses'] + self.assertEqual(len(addresses["public"]), len(public)) + self.assertEqual(addresses["public"][0], public[0]) + self.assertEqual(len(addresses["private"]), 1) + self.assertEqual(addresses["private"][0], private) + def test_get_server_list(self): req = webob.Request.blank('/v1.0/servers') res = req.get_response(fakes.wsgi_app()) -- cgit From 4a4a3f04b78ba2cbaa0d02ecf0f7cd3cf580901b Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 9 Feb 2011 21:54:52 -0500 Subject: adding myself to Authors file --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 27782738f..563ddf759 100644 --- a/Authors +++ b/Authors @@ -3,6 +3,7 @@ Anne Gentle Anthony Young Antony Messerli Armando Migliaccio +Brian Waldon Chiradeep Vittal Chmouel Boudjnah Chris Behrens -- cgit From 16ffc15b1fb45a09de14cece6b382357a030b9dc Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 10 Feb 2011 08:43:46 -0400 Subject: removed ZoneCommands from nova-manage --- bin/nova-manage | 10 ---------- nova/api/openstack/__init__.py | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index b62687aec..7835ca551 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -569,15 +569,6 @@ class DbCommands(object): print migration.db_version() -class ZoneCommands(object): - """Methods for defining zones.""" - - def create(self, name): - """Create a new Zone for this deployment.""" - ctxt = context.get_admin_context() - db.create_zone(ctxt, name) - - class VolumeCommands(object): """Methods for dealing with a cloud in an odd state""" @@ -629,7 +620,6 @@ CATEGORIES = [ ('service', ServiceCommands), ('log', LogCommands), ('db', DbCommands), - ('zone', ZoneCommands), ('volume', VolumeCommands)] diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 8901a8987..69a4d66c0 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -80,7 +80,7 @@ class APIRouter(wsgi.Router): server_members["actions"] = "GET" server_members['suspend'] = 'POST' server_members['resume'] = 'POST' - + mapper.resource("zone", "zones", controller=zones.Controller(), collection={'detail': 'GET'}, collection_name='zones') -- cgit From 389b548e332a496bcc74d637030f753c66add570 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 10 Feb 2011 16:08:19 -0400 Subject: template adjusted to NOVA_TOOLS, zone db & os api layers added --- nova/api/openstack/zones.py | 75 ++++++++++++++++++++++++++++++++++++++++++++ nova/auth/novarc.template | 7 ++--- nova/db/api.py | 26 +++++++++++++-- nova/db/sqlalchemy/api.py | 41 ++++++++++++++++++++++-- nova/db/sqlalchemy/models.py | 11 ++++++- 5 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 nova/api/openstack/zones.py diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/zones.py new file mode 100644 index 000000000..a12d1cc0c --- /dev/null +++ b/nova/api/openstack/zones.py @@ -0,0 +1,75 @@ +# Copyright 2010 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. + +import logging + +from nova import flags +from nova import wsgi +from nova import db + + +FLAGS = flags.FLAGS + + +def _filter_keys(item, keys): + """ + Filters all model attributes except for keys + item is a dict + + """ + return dict((k, v) for k, v in item.iteritems() if k in keys) + + +class Controller(wsgi.Controller): + + _serialization_metadata = { + 'application/xml': { + "attributes": { + "zone": ["id", "api_url"]}}} + + def index(self, req): + """Return all zones in brief""" + items = db.zone_get_all(req.environ['nova.context']) + items = common.limited(items, req) + items = [_filter_keys(item, ('id', 'api_url')) for item in items] + return dict(zones=items) + + def detail(self, req): + """Return all zones in detail""" + return self.index(req) + + def show(self, req, id): + """Return data about the given zone id""" + zone_id = int(id) + zone = db.zone_get(req.environ['nova.context'], zone_id) + return dict(zone=zone) + + def delete(self, req, id): + zone_id = int(id) + db.zone_delete(req.environ['nova.context'], zone_id) + return {} + + def create(self, req): + context = req.environ['nova.context'] + env = self._deserialize(req.body, req) + zone = db.zone_create(context, env["zone"]) + return dict(zone=zone) + + def update(self, req, id): + context = req.environ['nova.context'] + env = self._deserialize(req.body, req) + zone_id = int(id) + zone = db.zone_update(context, zone_id, env["zone"]) + return dict(zone=zone) diff --git a/nova/auth/novarc.template b/nova/auth/novarc.template index c53a4acdc..702df3bb0 100644 --- a/nova/auth/novarc.template +++ b/nova/auth/novarc.template @@ -10,7 +10,6 @@ export NOVA_CERT=${NOVA_KEY_DIR}/%(nova)s export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}" alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}" -export CLOUD_SERVERS_API_KEY="%(access)s" -export CLOUD_SERVERS_USERNAME="%(user)s" -export CLOUD_SERVERS_URL="%(os)s" - +export NOVA_TOOLS_API_KEY="%(access)s" +export NOVA_TOOLS_USERNAME="%(user)s" +export NOVA_TOOLS_URL="%(os)s" diff --git a/nova/db/api.py b/nova/db/api.py index dc35f20b2..fa73d86ad 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -985,6 +985,26 @@ def console_get(context, console_id, instance_id=None): #################### -def create_zone(context, name): - """Create a new Zone entry for this deployment.""" - return IMPL.create_zone(context, name) +def zone_create(context, values): + """Create a new ChildZone entry in this Zone.""" + return IMPL.zone_create(context, values) + + +def zone_update(context, zone_id, values): + """Update a ChildZone entry in this Zone.""" + return IMPL.zone_update(context, values) + + +def zone_delete(context, zone_id): + """Delete a ChildZone.""" + return IMPL.zone_delete(context, zone_id) + + +def zone_get(context, zone_id): + """Get a specific ChildZone.""" + return IMPL.zone_get(context, zone_id) + + +def zone_get_all(context): + """Get all ChildZone's.""" + return IMPL.zone_get_all(context) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index f568d3470..cdd6db25f 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2010,10 +2010,45 @@ def console_get(context, console_id, instance_id=None): return result -################## +#################### + + +@require_admin_context +def zone_create(context, values): + zone = models.ChildZone() + zone.update(values) + zone.save() + return zone + + +@require_admin_context +def zone_update(context, zone_id, values): + zone = session.query(models.ChildZone).filter_by(id=zone_id).first() + if not zone: + raise exception.NotFound(_("No zone with id %(zone_id)s") % locals()) + zone.update(values) + zone.save() + return zone + + +@require_admin_context +def zone_delete(context, zone_id): + session = get_session() + with session.begin(): + session.execute('delete from childzones ' + 'where id=:id', {'id': zone_id}) + + +@require_admin_context +def zone_get(context, zone_id): + session = get_session() + result = session.query(models.ChildZone).filter_by(id=zone_id).first() + if not result: + raise exception.NotFound(_("No zone with id %(zone_id)s") % locals()) + return result @require_admin_context -def create_zone(context, zone): +def zone_get_all(context): session = get_session() - print "Creating Zone", zone + return session.query(models.ChildZone).filter_by(id=zone_id).all() diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 7efb36c0e..3c677cad8 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -535,6 +535,15 @@ class Console(BASE, NovaBase): pool = relationship(ConsolePool, backref=backref('consoles')) +class ChildZone(BASE, NovaBase): + """Represents a child zone of this zone.""" + __tablename__ = 'childzones' + id = Column(Integer, primary_key=True) + api_url = Column(String(255)) + username = Column(String(255)) + password = Column(String(255)) + + def register_models(): """Register Models and create metadata. @@ -547,7 +556,7 @@ def register_models(): Volume, ExportDevice, IscsiTarget, FixedIp, FloatingIp, Network, SecurityGroup, SecurityGroupIngressRule, SecurityGroupInstanceAssociation, AuthToken, User, - Project, Certificate, ConsolePool, Console) # , Image, Host + Project, Certificate, ConsolePool, Console, ChildZone) engine = create_engine(FLAGS.sql_connection, echo=False) for model in models: model.metadata.create_all(engine) -- cgit From b0c6190e0b098af4d808d993c6dcd0796cc80e83 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 10 Feb 2011 14:18:16 -0600 Subject: forgot to add network_get_all_by_instance to db.api --- nova/db/api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nova/db/api.py b/nova/db/api.py index f22cd5615..a38f187a8 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -522,6 +522,11 @@ def network_get_by_instance(context, instance_id): return IMPL.network_get_by_instance(context, instance_id) +def network_get_all_by_instance(context, instance_id): + """Get all networks by instance id or raise if it does not exist.""" + return IMPL.network_get_all_by_instance(context, instance_id) + + def network_get_index(context, network_id): """Get non-conflicting index for network.""" return IMPL.network_get_index(context, network_id) -- cgit From 87d0b5203610f1e0a7a2e09033c79071fabacaba Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 10 Feb 2011 15:01:31 -0600 Subject: passing instance to reset_network instead of vm_ref, also not converting to an opaque ref before making plugin call --- nova/virt/xenapi/vmops.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 4056e99bc..575e53f80 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -121,7 +121,7 @@ class VMOps(object): network_ref, instance.mac_address) # call reset networking - self.reset_network(vm_ref) + self.reset_network(instance) LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) @@ -393,9 +393,8 @@ class VMOps(object): return 'http://fakeajaxconsole/fake_url' def reset_network(self, instance): - vm = self._get_vm_opaque_ref(instance) args = {'id': str(uuid.uuid4())} - resp = self._make_agent_call('resetnetwork', vm, '', args) + resp = self._make_agent_call('resetnetwork', instance, '', args) def list_from_xenstore(self, vm, path): """Runs the xenstore-ls command to get a listing of all records -- cgit From 96640472934c4eba48c6ab0048ac5bcf3c192eb4 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 10 Feb 2011 15:25:26 -0600 Subject: added resetnetwork to the XenAPIPlugin.dispatch dict --- plugins/xenserver/xenapi/etc/xapi.d/plugins/agent | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index 5c5ec7c45..b4c742396 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -135,4 +135,5 @@ def _wait_for_agent(self, request_id, arg_dict): if __name__ == "__main__": XenAPIPlugin.dispatch( {"key_init": key_init, - "password": password}) + "password": password, + "resetnetwork": resetnetwork}) -- cgit From 57e58ba23c5c6a1af0f132385d3d9b9cc370b47d Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 10 Feb 2011 16:26:08 -0600 Subject: added get IPs by instance --- nova/db/api.py | 5 +++++ nova/db/sqlalchemy/api.py | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/nova/db/api.py b/nova/db/api.py index a38f187a8..a2c1dbdce 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -294,6 +294,11 @@ def fixed_ip_get_by_address(context, address): return IMPL.fixed_ip_get_by_address(context, address) +def fixed_ip_get_all_by_instance(context, instance_id): + """Get fixed ips by instance or raise if none exist.""" + return IMPL.fixed_ip_get_all_by_instance(context, instance_id) + + def fixed_ip_get_instance(context, address): """Get an instance for a fixed ip by address.""" return IMPL.fixed_ip_get_instance(context, address) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 26b685e43..f20f4e266 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -606,6 +606,17 @@ def fixed_ip_get_instance(context, address): return fixed_ip_ref.instance +@require_context +def fixed_ip_get_all_by_instance(context, instance_id): + session = get_session() + rv = session.query(models.Network.fixed_ips).\ + filter_by(instance_id=instance_id).\ + filter_by(deleted=False) + if not rv: + raise exception.NotFound(_('No address for instance %s') % instance_id) + return rv + + @require_context def fixed_ip_get_instance_v6(context, address): session = get_session() -- cgit From c230dba962a3db2a3a8bb502dfb33313f0ef274b Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 11 Feb 2011 11:25:55 -0400 Subject: rough cut at zone api tests --- nova/tests/api/openstack/test_zones.py | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 nova/tests/api/openstack/test_zones.py diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py new file mode 100644 index 000000000..8a817bebe --- /dev/null +++ b/nova/tests/api/openstack/test_zones.py @@ -0,0 +1,74 @@ +# Copyright 2010 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. + +import unittest + +import stubout +import webob + +import nova.api +from nova.api.openstack import zones +from nova.tests.api.openstack import fakes + + +class ZonesTest(unittest.TestCase): + def setUp(self): + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + + def tearDown(self): + self.stubs.UnsetAll() + + def test_get_zone_list(self): + req = webob.Request.blank('/v1.0/zones') + res = req.get_response(fakes.wsgi_app()) + + def test_get_zone_by_id(self): + req = webob.Request.blank('/v1.0/zones/1') + res = req.get_response(fakes.wsgi_app()) + + def test_zone_delete(self): + req = webob.Request.blank('/v1.0/zones/1') + res = req.get_response(fakes.wsgi_app()) + + def test_zone_create(self): + body = dict(server=dict(api_url='http://blah.zoo', username='bob', + password='qwerty')) + req = webob.Request.blank('/v1.0/zones') + req.method = 'POST' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + + self.assertEqual(res.status_int, 200) + + def test_zone_update(self): + body = dict(server=dict(api_url='http://blah.zoo', username='zeb', + password='sneaky')) + req = webob.Request.blank('/v1.0/zones/1') + req.method = 'PUT' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + + self.assertEqual(res.status_int, 200) + + +if __name__ == '__main__': + unittest.main() -- cgit From df9bf23ecda1f32fd31ebffc6013e2f60f7fd3fa Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 11 Feb 2011 15:13:05 -0400 Subject: zone api tests passing --- nova/api/openstack/__init__.py | 3 +- nova/api/openstack/zones.py | 1 + nova/tests/api/openstack/test_zones.py | 81 +++++++++++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 8aeb69693..33d040ab3 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -82,8 +82,7 @@ class APIRouter(wsgi.Router): server_members['resume'] = 'POST' mapper.resource("zone", "zones", controller=zones.Controller(), - collection={'detail': 'GET'}, - collection_name='zones') + collection={'detail': 'GET'}) mapper.resource("server", "servers", controller=servers.Controller(), collection={'detail': 'GET'}, diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/zones.py index a12d1cc0c..e84b38fa9 100644 --- a/nova/api/openstack/zones.py +++ b/nova/api/openstack/zones.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import common import logging from nova import flags diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 8a817bebe..8dbdffa41 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -17,12 +17,50 @@ import unittest import stubout import webob +import json -import nova.api +import nova.db +from nova import context +from nova import flags from nova.api.openstack import zones from nova.tests.api.openstack import fakes +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +def zone_get(context, zone_id): + return dict(id=1, api_url='http://foo.com', username='bob', + password='xxx') + + +def zone_create(context, values): + zone = dict(id=1) + zone.update(values) + return zone + + +def zone_update(context, zone_id, values): + zone = dict(id=zone_id, api_url='http://foo.com', username='bob', + password='xxx') + zone.update(values) + return zone + + +def zone_delete(context, zone_id): + pass + + +def zone_get_all(context): + return [ + dict(id=1, api_url='http://foo.com', username='bob', + password='xxx'), + dict(id=2, api_url='http://blah.com', username='alice', + password='qwerty') + ] + + class ZonesTest(unittest.TestCase): def setUp(self): self.stubs = stubout.StubOutForTesting() @@ -32,42 +70,75 @@ class ZonesTest(unittest.TestCase): fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) + self.allow_admin = FLAGS.allow_admin_api + FLAGS.allow_admin_api = True + + self.stubs.Set(nova.db, 'zone_get', zone_get) + self.stubs.Set(nova.db, 'zone_get_all', zone_get_all) + self.stubs.Set(nova.db, 'zone_update', zone_update) + self.stubs.Set(nova.db, 'zone_create', zone_create) + self.stubs.Set(nova.db, 'zone_delete', zone_delete) + def tearDown(self): self.stubs.UnsetAll() + FLAGS.allow_admin_api = self.allow_admin def test_get_zone_list(self): req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_by_id(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['username'], 'bob') + self.assertEqual(res_dict['zone']['password'], 'xxx') + + self.assertEqual(res.status_int, 200) def test_zone_delete(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + def test_zone_create(self): - body = dict(server=dict(api_url='http://blah.zoo', username='bob', - password='qwerty')) + body = dict(zone=dict(api_url='http://blah.zoo', username='fred', + password='fubar')) req = webob.Request.blank('/v1.0/zones') req.method = 'POST' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') + self.assertEqual(res_dict['zone']['username'], 'fred') + self.assertEqual(res_dict['zone']['password'], 'fubar') def test_zone_update(self): - body = dict(server=dict(api_url='http://blah.zoo', username='zeb', - password='sneaky')) + body = dict(zone=dict(username='zeb', password='sneaky')) req = webob.Request.blank('/v1.0/zones/1') req.method = 'PUT' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['username'], 'zeb') + self.assertEqual(res_dict['zone']['password'], 'sneaky') if __name__ == '__main__': -- cgit From 9c0862b5f84cdb09b7ab0aafca669d30f261a666 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Mon, 14 Feb 2011 10:21:16 -0600 Subject: support for multiple IPs per network --- nova/virt/xenapi/vmops.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 575e53f80..db05a24ff 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -96,22 +96,36 @@ class VMOps(object): # write network info admin_context = context.get_admin_context() - #network = db.network_get_by_instance(admin_context, - # instance['id']) + # TODO(tr3buchet) - remove comment in multi-nic + # I've decided to go ahead and consider multiple IPs and networks + # at this stage even though they aren't implemented because these will + # be needed for multi-nic and there was no sense writing it for single + # network/single IP and then having to turn around and re-write it + IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) for network in db.network_get_all_by_instance(admin_context, instance['id']): + network_IPs = [ip for ip in IPs if ip.network_id == network.id] + + def ip_dict(ip): + return {'netmask': network['netmask'], + 'enabled': '1', + 'ip': ip.address} + mac_id = instance.mac_address.replace(':', '') location = 'vm-data/networking/%s' % mac_id mapping = {'label': network['label'], 'gateway': network['gateway'], 'mac': instance.mac_address, 'dns': [network['dns']], - 'ips': [{'netmask': network['netmask'], - 'enabled': '1', - 'ip': '192.168.3.3'}]} # <===== CHANGE!!!! + 'ips': [ip_dict(ip) for ip in network_IPs]} self.write_to_param_xenstore(vm_ref, {location: mapping}) + # TODO(tr3buchet) - remove comment in multi-nic + # this bit here about creating the vifs will be updated + # in multi-nic to handle multiple IPs on the same network + # and multiple networks + # for now it works as there is only one of each bridge = network['bridge'] network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) -- cgit From ee26d0827b7ad3e4d7869614835fe58abe32dfc8 Mon Sep 17 00:00:00 2001 From: Ricardo Carrillo Cruz Date: Mon, 14 Feb 2011 17:43:39 +0100 Subject: Got rid of BadParameter, just using standard python ValueError --- nova/network/manager.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nova/network/manager.py b/nova/network/manager.py index 8eb9f041b..d911844a1 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -505,6 +505,12 @@ class VlanManager(NetworkManager): def create_networks(self, context, cidr, num_networks, network_size, cidr_v6, vlan_start, vpn_start): """Create networks based on parameters.""" + # Check that num_networks + vlan_start is not > 4094, fixes lp708025 + if num_networks + vlan_start > 4094: + raise ValueError(_('The sum between the number of networks and' + ' the vlan start cannot be greater' + ' than 4094')) + fixed_net = IPy.IP(cidr) fixed_net_v6 = IPy.IP(cidr_v6) network_size_v6 = 1 << 64 -- cgit From 3f96e6dbf12533355aa6722eeb498814df076aea Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Mon, 14 Feb 2011 12:32:33 -0600 Subject: added call to reset_network from openstack api down to vmops --- nova/api/openstack/servers.py | 14 ++++++++++++++ nova/compute/api.py | 9 ++++++++- nova/compute/manager.py | 12 ++++++++++++ nova/virt/xenapi_conn.py | 4 ++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 8cbcebed2..c604bd215 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -242,6 +242,20 @@ class Controller(wsgi.Controller): return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() + def reset_network(self, req, id): + """ + admin only operation which resets networking on an instance + + """ + context = req.environ['nova.context'] + try: + self.compute_api.reset_network(context, id) + except: + readable = traceback.format_exc() + LOG.exception(_("Compute.api::reset_network %s"), readable) + return faults.Fault(exc.HTTPUnprocessableEntity()) + return exc.HTTPAccepted() + def pause(self, req, id): """ Permit Admins to Pause the server. """ ctxt = req.environ['nova.context'] diff --git a/nova/compute/api.py b/nova/compute/api.py index 6a3fe08b6..43332ed27 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1,4 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# vim: tabstop=5 shiftwidth=4 softtabstop=4 # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. @@ -463,6 +463,13 @@ class API(base.Base): instance = self.get(context, instance_id) return instance['locked'] + def reset_network(self, context, instance_id): + """ + resets networking on the instance + + """ + self._cast_compute_message('reset_network', context, instance_id) + def attach_volume(self, context, instance_id, volume_id, device): if not re.match("^/dev/[a-z]d[a-z]+$", device): raise exception.ApiError(_("Invalid device specified: %s. " diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 6f09ce674..b03f58693 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -494,6 +494,18 @@ class ComputeManager(manager.Manager): instance_ref = self.db.instance_get(context, instance_id) return instance_ref['locked'] + @checks_instance_lock + def reset_network(self, context, instance_id): + """ + resets the networking on the instance + + """ + context = context.elevated() + instance_ref = self.db.instance_get(context, instance_id) + LOG.debug(_('instance %s: reset network'), instance_id, + context=context) + self.driver.reset_network(instance_ref) + @exception.wrap_exception def get_console_output(self, context, instance_id): """Send the console output for an instance.""" diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 927f5905b..4e5442aa6 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -188,6 +188,10 @@ class XenAPIConnection(object): """resume the specified instance""" self._vmops.resume(instance, callback) + def reset_network(self, instance): + """reset networking for specified instance""" + self._vmops.reset_network(instance) + def get_info(self, instance_id): """Return data about VM instance""" return self._vmops.get_info(instance_id) -- cgit From ee4cba7779daa5b2e7415fb69cabc698b7dd60da Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Mon, 14 Feb 2011 12:59:46 -0600 Subject: corrected model for table lookup --- nova/db/sqlalchemy/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index f20f4e266..827f81ae2 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -609,7 +609,7 @@ def fixed_ip_get_instance(context, address): @require_context def fixed_ip_get_all_by_instance(context, instance_id): session = get_session() - rv = session.query(models.Network.fixed_ips).\ + rv = session.query(models.FixedIp).\ filter_by(instance_id=instance_id).\ filter_by(deleted=False) if not rv: -- cgit From 6147a606cbe6b7e764865d2471d86f503437051b Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 14 Feb 2011 14:52:58 -0800 Subject: fixed template and added migration --- nova/auth/novarc.template | 6 +-- .../sqlalchemy/migrate_repo/versions/003_cactus.py | 62 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py diff --git a/nova/auth/novarc.template b/nova/auth/novarc.template index 702df3bb0..cda2ecc28 100644 --- a/nova/auth/novarc.template +++ b/nova/auth/novarc.template @@ -10,6 +10,6 @@ export NOVA_CERT=${NOVA_KEY_DIR}/%(nova)s export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}" alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}" -export NOVA_TOOLS_API_KEY="%(access)s" -export NOVA_TOOLS_USERNAME="%(user)s" -export NOVA_TOOLS_URL="%(os)s" +export NOVA_API_KEY="%(access)s" +export NOVA_USERNAME="%(user)s" +export NOVA_URL="%(os)s" diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py new file mode 100644 index 000000000..eb3287077 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py @@ -0,0 +1,62 @@ +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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 log as logging + + +meta = MetaData() + + +# +# New Tables +# +child_zones = Table('child_zones', meta, + Column('created_at', DateTime(timezone=False)), + Column('updated_at', DateTime(timezone=False)), + Column('deleted_at', DateTime(timezone=False)), + Column('deleted', Boolean(create_constraint=True, name=None)), + Column('id', Integer(), primary_key=True, nullable=False), + Column('api_url', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('username', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('password', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + ) + + +# +# Tables to alter +# + +# (none currently) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + for table in (child_zones, ): + try: + table.create() + except Exception: + logging.info(repr(table)) -- cgit From 1da5dcc0644a13cfb99852f3438649f710feb2bc Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 14 Feb 2011 14:54:04 -0800 Subject: removed debugging --- nova/api/openstack/auth.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index a383ef086..473071738 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -79,7 +79,6 @@ class AuthMiddleware(wsgi.Middleware): except KeyError: return faults.Fault(webob.exc.HTTPUnauthorized()) - logging.debug("**** USERNAME %s, PASSWORD %s" % (username, key)) token, user = self._authorize_user(username, key, req) if user and token: res = webob.Response() -- cgit From e65291cf34894322bd0f3f6661907e48e7a6a0b5 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 14 Feb 2011 20:11:29 -0400 Subject: fixed nova-combined debug hack and renamed ChildZone to Zone --- bin/nova-combined | 4 ++-- nova/db/api.py | 10 +++++----- nova/db/sqlalchemy/api.py | 10 +++++----- nova/db/sqlalchemy/migration.py | 2 +- nova/db/sqlalchemy/models.py | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bin/nova-combined b/bin/nova-combined index a0f552d64..913c866bf 100755 --- a/bin/nova-combined +++ b/bin/nova-combined @@ -53,11 +53,11 @@ if __name__ == '__main__': compute = service.Service.create(binary='nova-compute') network = service.Service.create(binary='nova-network') - #volume = service.Service.create(binary='nova-volume') + volume = service.Service.create(binary='nova-volume') scheduler = service.Service.create(binary='nova-scheduler') #objectstore = service.Service.create(binary='nova-objectstore') - service.serve(compute, network, scheduler) + service.serve(compute, network, volume, scheduler) apps = [] paste_config_file = wsgi.paste_config_file('nova-api.conf') diff --git a/nova/db/api.py b/nova/db/api.py index fa73d86ad..939f1a069 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -986,25 +986,25 @@ def console_get(context, console_id, instance_id=None): def zone_create(context, values): - """Create a new ChildZone entry in this Zone.""" + """Create a new child Zone entry.""" return IMPL.zone_create(context, values) def zone_update(context, zone_id, values): - """Update a ChildZone entry in this Zone.""" + """Update a child Zone entry.""" return IMPL.zone_update(context, values) def zone_delete(context, zone_id): - """Delete a ChildZone.""" + """Delete a child Zone.""" return IMPL.zone_delete(context, zone_id) def zone_get(context, zone_id): - """Get a specific ChildZone.""" + """Get a specific child Zone.""" return IMPL.zone_get(context, zone_id) def zone_get_all(context): - """Get all ChildZone's.""" + """Get all child Zones.""" return IMPL.zone_get_all(context) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index b3320c819..abd65b67b 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -2021,7 +2021,7 @@ def console_get(context, console_id, instance_id=None): @require_admin_context def zone_create(context, values): - zone = models.ChildZone() + zone = models.Zone() zone.update(values) zone.save() return zone @@ -2029,7 +2029,7 @@ def zone_create(context, values): @require_admin_context def zone_update(context, zone_id, values): - zone = session.query(models.ChildZone).filter_by(id=zone_id).first() + zone = session.query(models.Zone).filter_by(id=zone_id).first() if not zone: raise exception.NotFound(_("No zone with id %(zone_id)s") % locals()) zone.update(values) @@ -2041,14 +2041,14 @@ def zone_update(context, zone_id, values): def zone_delete(context, zone_id): session = get_session() with session.begin(): - session.execute('delete from child_zones ' + session.execute('delete from zones ' 'where id=:id', {'id': zone_id}) @require_admin_context def zone_get(context, zone_id): session = get_session() - result = session.query(models.ChildZone).filter_by(id=zone_id).first() + result = session.query(models.Zone).filter_by(id=zone_id).first() if not result: raise exception.NotFound(_("No zone with id %(zone_id)s") % locals()) return result @@ -2057,4 +2057,4 @@ def zone_get(context, zone_id): @require_admin_context def zone_get_all(context): session = get_session() - return session.query(models.ChildZone).all() + return session.query(models.Zone).all() diff --git a/nova/db/sqlalchemy/migration.py b/nova/db/sqlalchemy/migration.py index 194ecc627..1d9c041f5 100644 --- a/nova/db/sqlalchemy/migration.py +++ b/nova/db/sqlalchemy/migration.py @@ -45,7 +45,7 @@ def db_version(): engine = sqlalchemy.create_engine(FLAGS.sql_connection, echo=False) meta.reflect(bind=engine) try: - for table in ('auth_tokens', 'child_zones', 'export_devices', + for table in ('auth_tokens', 'zones', 'export_devices', 'fixed_ips', 'floating_ips', 'instances', 'key_pairs', 'networks', 'projects', 'quotas', 'security_group_instance_association', diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 071d57fca..4930c7a2a 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -535,9 +535,9 @@ class Console(BASE, NovaBase): pool = relationship(ConsolePool, backref=backref('consoles')) -class ChildZone(BASE, NovaBase): +class Zone(BASE, NovaBase): """Represents a child zone of this zone.""" - __tablename__ = 'child_zones' + __tablename__ = 'zones' id = Column(Integer, primary_key=True) api_url = Column(String(255)) username = Column(String(255)) @@ -556,7 +556,7 @@ def register_models(): Volume, ExportDevice, IscsiTarget, FixedIp, FloatingIp, Network, SecurityGroup, SecurityGroupIngressRule, SecurityGroupInstanceAssociation, AuthToken, User, - Project, Certificate, ConsolePool, Console, ChildZone) + Project, Certificate, ConsolePool, Console, Zone) engine = create_engine(FLAGS.sql_connection, echo=False) for model in models: model.metadata.create_all(engine) -- cgit From c15289a63c90218a573d5e75833985ec2ad8691e Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 14 Feb 2011 23:02:26 -0400 Subject: better filtering --- nova/api/openstack/zones.py | 13 ++++++++----- nova/tests/api/openstack/test_zones.py | 10 +++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/zones.py index 2c93c0c7b..830464ffd 100644 --- a/nova/api/openstack/zones.py +++ b/nova/api/openstack/zones.py @@ -33,6 +33,10 @@ def _filter_keys(item, keys): return dict((k, v) for k, v in item.iteritems() if k in keys) +def _scrub_zone(zone): + return _filter_keys(zone, ('id', 'api_url')) + + class Controller(wsgi.Controller): _serialization_metadata = { @@ -44,7 +48,7 @@ class Controller(wsgi.Controller): """Return all zones in brief""" items = db.zone_get_all(req.environ['nova.context']) items = common.limited(items, req) - items = [_filter_keys(item, ('id', 'api_url')) for item in items] + items = [_scrub_zone(item) for item in items] return dict(zones=items) def detail(self, req): @@ -55,8 +59,7 @@ class Controller(wsgi.Controller): """Return data about the given zone id""" zone_id = int(id) zone = db.zone_get(req.environ['nova.context'], zone_id) - zone = _filter_keys(zone, ('id', 'api_url')) - return dict(zone=zone) + return dict(zone=_scrub_zone(zone)) def delete(self, req, id): zone_id = int(id) @@ -67,11 +70,11 @@ class Controller(wsgi.Controller): context = req.environ['nova.context'] env = self._deserialize(req.body, req) zone = db.zone_create(context, env["zone"]) - return dict(zone=zone) + return dict(zone=_scrub_zone(zone)) def update(self, req, id): context = req.environ['nova.context'] env = self._deserialize(req.body, req) zone_id = int(id) zone = db.zone_update(context, zone_id, env["zone"]) - return dict(zone=zone) + return dict(zone=_scrub_zone(zone)) diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 8dbdffa41..5542a1cf3 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -98,9 +98,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') - self.assertEqual(res_dict['zone']['username'], 'bob') - self.assertEqual(res_dict['zone']['password'], 'xxx') - + self.assertFalse('password' in res_dict['zone']) self.assertEqual(res.status_int, 200) def test_zone_delete(self): @@ -122,8 +120,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') - self.assertEqual(res_dict['zone']['username'], 'fred') - self.assertEqual(res_dict['zone']['password'], 'fubar') + self.assertFalse('username' in res_dict['zone']) def test_zone_update(self): body = dict(zone=dict(username='zeb', password='sneaky')) @@ -137,8 +134,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') - self.assertEqual(res_dict['zone']['username'], 'zeb') - self.assertEqual(res_dict['zone']['password'], 'sneaky') + self.assertFalse('username' in res_dict['zone']) if __name__ == '__main__': -- cgit From 5a988eb393c306097250a7f17ea65f0919fd9219 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 15 Feb 2011 12:43:29 -0400 Subject: fixed / renamed migration scripts --- .../migrate_repo/versions/003_add_zone_tables.py | 62 ++++++++++++++++++++++ .../sqlalchemy/migrate_repo/versions/003_cactus.py | 62 ---------------------- 2 files changed, 62 insertions(+), 62 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_add_zone_tables.py delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_add_zone_tables.py b/nova/db/sqlalchemy/migrate_repo/versions/003_add_zone_tables.py new file mode 100644 index 000000000..d2b6b9570 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_add_zone_tables.py @@ -0,0 +1,62 @@ +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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 log as logging + + +meta = MetaData() + + +# +# New Tables +# +zones = Table('zones', meta, + Column('created_at', DateTime(timezone=False)), + Column('updated_at', DateTime(timezone=False)), + Column('deleted_at', DateTime(timezone=False)), + Column('deleted', Boolean(create_constraint=True, name=None)), + Column('id', Integer(), primary_key=True, nullable=False), + Column('api_url', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('username', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('password', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + ) + + +# +# Tables to alter +# + +# (none currently) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + for table in (zones, ): + try: + table.create() + except Exception: + logging.info(repr(table)) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py deleted file mode 100644 index eb3287077..000000000 --- a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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 log as logging - - -meta = MetaData() - - -# -# New Tables -# -child_zones = Table('child_zones', meta, - Column('created_at', DateTime(timezone=False)), - Column('updated_at', DateTime(timezone=False)), - Column('deleted_at', DateTime(timezone=False)), - Column('deleted', Boolean(create_constraint=True, name=None)), - Column('id', Integer(), primary_key=True, nullable=False), - Column('api_url', - String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, _warn_on_bytestring=False)), - Column('username', - String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, _warn_on_bytestring=False)), - Column('password', - String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, _warn_on_bytestring=False)), - ) - - -# -# Tables to alter -# - -# (none currently) - - -def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; - # bind migrate_engine to your metadata - meta.bind = migrate_engine - for table in (child_zones, ): - try: - table.create() - except Exception: - logging.info(repr(table)) -- cgit From cbe4ee9f3a6bf207d475ca230032ced9325c3b7a Mon Sep 17 00:00:00 2001 From: brian-lamar Date: Tue, 15 Feb 2011 15:33:17 -0500 Subject: Added teammate Naveed to authors file for his help. --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index e8bb58456..03f30084d 100644 --- a/Authors +++ b/Authors @@ -43,6 +43,7 @@ Monty Taylor MORITA Kazutaka Muneyuki Noguchi Nachi Ueno +Naveed Massjouni Paul Voccio Ricardo Carrillo Cruz Rick Clark -- cgit From 503749849df73df1732583bc9452e7952bf78ac2 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 15 Feb 2011 15:25:48 -0600 Subject: moved reset network to after boot durrrrr... --- nova/virt/xenapi/vmops.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 00028cdaa..dd9f48ddf 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -134,9 +134,6 @@ class VMOps(object): VMHelper.create_vif(self._session, vm_ref, network_ref, instance.mac_address) - # call reset networking - self.reset_network(instance) - LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) instance_name = instance.name @@ -164,6 +161,10 @@ class VMOps(object): timer.stop() timer.f = _wait_for_boot + + # call reset networking + self.reset_network(instance) + return timer.start(interval=0.5, now=True) def _get_vm_opaque_ref(self, instance_or_vm): -- cgit From 1b9413e11ba1b4b49b50965e3f812e636f2319d5 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 15 Feb 2011 18:20:44 -0600 Subject: stubbed out reset networkin xenapi VM tests to solve domid problem --- nova/tests/test_xenapi.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index d5660c5d1..6b8efc9d8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -32,6 +32,7 @@ from nova.virt import xenapi_conn from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import volume_utils from nova.virt.xenapi.vmops import SimpleDH +from nova.virt.xenapi.vmops import VMOps from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs from nova.tests.glance import stubs as glance_stubs @@ -141,6 +142,10 @@ class XenAPIVolumeTestCase(test.TestCase): self.stubs.UnsetAll() +def reset_network(*args): + pass + + class XenAPIVMTestCase(test.TestCase): """ Unit tests for VM operations @@ -162,6 +167,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_stream_disk(self.stubs) + self.stubs.Set(VMOps, 'reset_network', reset_network) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) self.conn = xenapi_conn.get_connection(False) -- cgit From 7f8595b88df2271c278ae59b6d187b5c3b8dde40 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Wed, 16 Feb 2011 12:15:48 +0100 Subject: added functionality to nova-manage to list created networks --- bin/nova-manage | 12 ++++++++++++ nova/db/api.py | 5 +++++ nova/db/sqlalchemy/api.py | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index 7835ca551..f7cf77adb 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -499,6 +499,18 @@ class NetworkCommands(object): vlan_start=int(vlan_start), vpn_start=int(vpn_start)) + def list(self): + """List all created networks""" + print "%-18s\t%-15s\t%-15s\t%-15s" % ('CIDR', + 'netmask', + 'dhcp_start', + 'DNS') + for network in db.network_get_all(context.get_admin_context()): + print "%-18s\t%-15s\t%-15s\t%-15s" % (network.cidr, + network.netmask, + network.dhcp_start, + network.dns) + class ServiceCommands(object): """Enable and disable running services""" diff --git a/nova/db/api.py b/nova/db/api.py index 789cb8ebb..d06f3731f 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -500,6 +500,11 @@ def network_get(context, network_id): return IMPL.network_get(context, network_id) +def network_get_all(context): + """Return all defined networks.""" + return IMPL.network_get_all(context) + + # pylint: disable-msg=C0103 def network_get_associated_fixed_ips(context, network_id): """Get all network's ips that have been associated.""" diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 02855e7a9..a11572947 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1056,6 +1056,15 @@ def network_get(context, network_id, session=None): return result +@require_admin_context +def network_get_all(context): + session = get_session() + result = session.query(models.Network) + if not result: + raise exception.NotFound('No networks defined') + return result + + # NOTE(vish): pylint complains because of the long method name, but # it fits with the names of the rest of the methods # pylint: disable-msg=C0103 -- cgit From c6b8f129ae57da2ea0cd844150e58d4fac7eb71d Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Wed, 16 Feb 2011 14:12:54 -0600 Subject: added test for reset_network to openstack api tests, tabstop 5 to 4, renamed migration --- nova/api/openstack/__init__.py | 1 + nova/compute/api.py | 2 +- .../versions/003_add_label_to_networks.py | 52 ++++++++++++++++++++++ .../sqlalchemy/migrate_repo/versions/003_cactus.py | 52 ---------------------- nova/tests/api/openstack/test_servers.py | 12 +++++ 5 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py delete mode 100644 nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 056c7dd27..dc3738d4a 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -79,6 +79,7 @@ class APIRouter(wsgi.Router): server_members["actions"] = "GET" server_members['suspend'] = 'POST' server_members['resume'] = 'POST' + server_members['reset_network'] = 'POST' mapper.resource("server", "servers", controller=servers.Controller(), collection={'detail': 'GET'}, diff --git a/nova/compute/api.py b/nova/compute/api.py index 857028605..71879b5b7 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1,4 +1,4 @@ -# vim: tabstop=5 shiftwidth=4 softtabstop=4 +# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py b/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py new file mode 100644 index 000000000..ddfe114cb --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py @@ -0,0 +1,52 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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 log as logging + + +meta = MetaData() + + +networks = Table('networks', meta, + Column('id', Integer(), primary_key=True, nullable=False), + ) + + +# +# New Tables +# + + +# +# Tables to alter +# + +networks_label = Column( + 'label', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + networks.create_column(networks_label) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py b/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py deleted file mode 100644 index ddfe114cb..000000000 --- a/nova/db/sqlalchemy/migrate_repo/versions/003_cactus.py +++ /dev/null @@ -1,52 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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 log as logging - - -meta = MetaData() - - -networks = Table('networks', meta, - Column('id', Integer(), primary_key=True, nullable=False), - ) - - -# -# New Tables -# - - -# -# Tables to alter -# - -networks_label = Column( - 'label', - String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, _warn_on_bytestring=False)) - - -def upgrade(migrate_engine): - # Upgrade operations go here. Don't create your own engine; - # bind migrate_engine to your metadata - meta.bind = migrate_engine - networks.create_column(networks_label) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 724f14f19..89e192eed 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -281,6 +281,18 @@ class ServersTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) + def test_server_reset_network(self): + FLAGS.allow_admin_api = True + body = dict(server=dict( + name='server_test', imageId=2, flavorId=2, metadata={}, + personality={})) + req = webob.Request.blank('/v1.0/servers/1/reset_network') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + def test_server_diagnostics(self): req = webob.Request.blank("/v1.0/servers/1/diagnostics") req.method = "GET" -- cgit From 5f0340504784c1a0847e5b19aa9a317d9be16c20 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 16 Feb 2011 16:19:57 -0500 Subject: Added alternate email to mailmap --- .mailmap | 1 + Authors | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index c6f6c9a8b..a05520884 100644 --- a/.mailmap +++ b/.mailmap @@ -34,3 +34,4 @@ + diff --git a/Authors b/Authors index c57ca8aed..eb9d540bf 100644 --- a/Authors +++ b/Authors @@ -4,7 +4,6 @@ Anthony Young Antony Messerli Armando Migliaccio Bilal Akhtar -Brian Lamar Chiradeep Vittal Chmouel Boudjnah Chris Behrens -- cgit From 05b96f9ddd0cc54c74c55c170b2037eeeafb527a Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 16 Feb 2011 16:22:16 -0500 Subject: Accidently removed myself from Authors. --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index eb9d540bf..c57ca8aed 100644 --- a/Authors +++ b/Authors @@ -4,6 +4,7 @@ Anthony Young Antony Messerli Armando Migliaccio Bilal Akhtar +Brian Lamar Chiradeep Vittal Chmouel Boudjnah Chris Behrens -- cgit From 6b5823f0aa75707fad6ca38dde490a47b740c3da Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 16 Feb 2011 16:40:40 -0500 Subject: Flipped mailmap entries --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index a05520884..b2287d65f 100644 --- a/.mailmap +++ b/.mailmap @@ -34,4 +34,4 @@ - + -- cgit From 5faa6e59ff9dff02e8d583e6711bd08dd1f821fd Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 16 Feb 2011 14:15:41 -0800 Subject: add periodic disassociate from VlanManager to FlatDHCPManager. --- nova/network/manager.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/nova/network/manager.py b/nova/network/manager.py index 8eb9f041b..a4a4c6064 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -394,6 +394,18 @@ class FlatDHCPManager(FlatManager): like FlatDHCPManager. """ + def periodic_tasks(self, context=None): + """Tasks to be run at a periodic interval.""" + super(FlatDHCPManager, self).periodic_tasks(context) + now = datetime.datetime.utcnow() + timeout = FLAGS.fixed_ip_disassociate_timeout + time = now - datetime.timedelta(seconds=timeout) + num = self.db.fixed_ip_disassociate_all_by_timeout(context, + self.host, + time) + if num: + LOG.debug(_("Dissassociated %s stale fixed ip(s)"), num) + def init_host(self): """Do any initialization that needs to be run if this is a standalone service. -- cgit From f50101fcf845e93637f50e426ceb759641a20b76 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 17 Feb 2011 13:46:24 +0100 Subject: Make eth0 the default for FLAGS.public_interface. --- nova/network/linux_net.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index c1cbff7d8..535ce87bc 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -44,7 +44,7 @@ flags.DEFINE_string('dhcp_domain', flags.DEFINE_string('networks_path', '$state_path/networks', 'Location to keep network config files') -flags.DEFINE_string('public_interface', 'vlan1', +flags.DEFINE_string('public_interface', 'eth0', 'Interface for public IP addresses') flags.DEFINE_string('vlan_interface', 'eth0', 'network device for vlans') -- cgit From bf7ec579786d3f02e63fc870fdfcb1e9c2674f05 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Thu, 17 Feb 2011 15:14:45 +0100 Subject: added i18n of 'No networks defined' --- nova/db/sqlalchemy/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index a11572947..65436ab0f 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1061,7 +1061,7 @@ def network_get_all(context): session = get_session() result = session.query(models.Network) if not result: - raise exception.NotFound('No networks defined') + raise exception.NotFound(_('No networks defined')) return result -- cgit From e28ce7f82d1c89ab0c4e5ebfa98c12f502a33138 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 17 Feb 2011 09:48:16 -0500 Subject: removing superfluous pass statements; replacing list comprehension with for loop; alphabetizing imports --- nova/api/openstack/servers.py | 6 ++---- nova/tests/api/openstack/test_servers.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 60f3d96e3..312d83ba5 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -72,15 +72,13 @@ def _translate_detail_keys(inst): inst_dict['addresses']['private'].append(private_ip) except KeyError: LOG.debug(_("Failed to read private ip")) - pass # grab all public floating ips try: - [inst_dict['addresses']['public'].append(floating['address']) \ - for floating in inst['fixed_ip']['floating_ips']] + for floating in inst['fixed_ip']['floating_ips']: + inst_dict['addresses']['public'].append(floating['address']) except KeyError: LOG.debug(_("Failed to read public ip(s)")) - pass inst_dict['metadata'] = {} inst_dict['hostId'] = '' diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 816a0ab8c..ace3b6850 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -15,9 +15,9 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime import json import unittest -import datetime import stubout import webob -- cgit From 5b97ee78b1bc2073bca0204caf92ae4560ec1e8e Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Thu, 17 Feb 2011 16:46:55 +0100 Subject: added more I18N --- bin/nova-manage | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index f7cf77adb..c64277908 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -501,9 +501,9 @@ class NetworkCommands(object): def list(self): """List all created networks""" - print "%-18s\t%-15s\t%-15s\t%-15s" % ('CIDR', - 'netmask', - 'dhcp_start', + print "%-18s\t%-15s\t%-15s\t%-15s" % (_('network'), + _('netmask'), + _('start address'), 'DNS') for network in db.network_get_all(context.get_admin_context()): print "%-18s\t%-15s\t%-15s\t%-15s" % (network.cidr, -- cgit From 7bb9e4c598f829a16cc6444346e087ddb506182a Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Thu, 17 Feb 2011 16:58:00 +0100 Subject: added new functionality to list all defined fixed ips --- bin/nova-manage | 31 +++++++++++++++++++++++++++++++ nova/db/api.py | 5 +++++ nova/db/sqlalchemy/api.py | 11 +++++++++++ 3 files changed, 47 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index e4c0684c4..a8c9441e2 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -433,6 +433,37 @@ class ProjectCommands(object): "nova-api server on this host.") +class FixedIpCommands(object): + """Class for managing fixed ip.""" + + def list(self, host=None): + """Lists all fixed ips (optionally by host) arguments: [host]""" + ctxt = context.get_admin_context() + if host == None: + fixed_ips = db.fixed_ip_get_all(ctxt) + else: + fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host) + + print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (_('network'), + _('IP address'), + _('MAC address'), + _('hostname'), + _('host')) + for fixed_ip in fixed_ips: + hostname = None + host = None + mac_address = None + if fixed_ip['instance']: + instance = fixed_ip['instance'] + hostname = instance['hostname'] + host = instance['host'] + mac_address = instance['mac_address'] + print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % ( + fixed_ip['network']['cidr'], + fixed_ip['address'], + mac_address, hostname, host) + + class FloatingIpCommands(object): """Class for managing floating ip.""" diff --git a/nova/db/api.py b/nova/db/api.py index 789cb8ebb..2b621044a 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -288,6 +288,11 @@ def fixed_ip_disassociate_all_by_timeout(context, host, time): return IMPL.fixed_ip_disassociate_all_by_timeout(context, host, time) +def fixed_ip_get_all(context): + """Get all defined fixed ips.""" + return IMPL.fixed_ip_get_all(context) + + def fixed_ip_get_by_address(context, address): """Get a fixed ip by address or raise if it does not exist.""" return IMPL.fixed_ip_get_by_address(context, address) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 02855e7a9..55f2f28bd 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -583,6 +583,17 @@ def fixed_ip_disassociate_all_by_timeout(_context, host, time): return result.rowcount +@require_admin_context +def fixed_ip_get_all(context, session=None): + if not session: + session = get_session() + result = session.query(models.FixedIp).all() + if not result: + raise exception.NotFound(_('No fixed ips defined')) + + return result + + @require_context def fixed_ip_get_by_address(context, address, session=None): if not session: -- cgit From 0b4641a90e5f51cddccb9886902a90d64ceb3200 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Thu, 17 Feb 2011 17:10:51 +0100 Subject: added entry in the category list --- bin/nova-manage | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/nova-manage b/bin/nova-manage index a8c9441e2..ddc78f7e5 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -653,6 +653,7 @@ CATEGORIES = [ ('role', RoleCommands), ('shell', ShellCommands), ('vpn', VpnCommands), + ('fixed', FixedIpCommands), ('floating', FloatingIpCommands), ('network', NetworkCommands), ('service', ServiceCommands), -- cgit From 28b77765fd38038fd7093589170dead48ffc417f Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 17 Feb 2011 12:13:20 -0500 Subject: Switched mailmap entries --- .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index b2287d65f..a05520884 100644 --- a/.mailmap +++ b/.mailmap @@ -34,4 +34,4 @@ - + -- cgit From ea4d21b546d9447bac50cf97a62c11129da12d21 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 17 Feb 2011 13:10:37 -0600 Subject: comments + Englilish, changed copyright in migration, removed network_get_all from db.api (vestigial) --- nova/api/openstack/servers.py | 2 +- nova/compute/api.py | 2 +- nova/compute/manager.py | 2 +- nova/db/api.py | 7 +------ .../sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py | 3 +-- nova/virt/xenapi/vmops.py | 6 ++++++ plugins/xenserver/xenapi/etc/xapi.d/plugins/agent | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 8b72704ba..33cc3bbde 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -251,7 +251,7 @@ class Controller(wsgi.Controller): def reset_network(self, req, id): """ - admin only operation which resets networking on an instance + Reset networking on an instance (admin only). """ context = req.environ['nova.context'] diff --git a/nova/compute/api.py b/nova/compute/api.py index 71879b5b7..ed6f0e34a 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -468,7 +468,7 @@ class API(base.Base): def reset_network(self, context, instance_id): """ - resets networking on the instance + Reset networking on the instance. """ self._cast_compute_message('reset_network', context, instance_id) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 1e2b95294..6fab1a41c 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -501,7 +501,7 @@ class ComputeManager(manager.Manager): @checks_instance_lock def reset_network(self, context, instance_id): """ - resets the networking on the instance + Reset networking on the instance. """ context = context.elevated() diff --git a/nova/db/api.py b/nova/db/api.py index 850a5126f..ce3395932 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -505,11 +505,6 @@ def network_get(context, network_id): return IMPL.network_get(context, network_id) -def network_get_all(context): - """Get all networks""" - return IMPL.network_get_all(context) - - # pylint: disable-msg=C0103 def network_get_associated_fixed_ips(context, network_id): """Get all network's ips that have been associated.""" @@ -527,7 +522,7 @@ def network_get_by_instance(context, instance_id): def network_get_all_by_instance(context, instance_id): - """Get all networks by instance id or raise if it does not exist.""" + """Get all networks by instance id or raise if none exist.""" return IMPL.network_get_all_by_instance(context, instance_id) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py b/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py index ddfe114cb..5ba7910f1 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 OpenStack LLC # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ea99ff626..842e08f22 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -151,6 +151,8 @@ class VMOps(object): % locals()) # NOTE(armando): Do we really need to do this in virt? + # NOTE(tr3buchet): not sure but wherever we do it, we need to call + # reset_network afterwards timer = utils.LoopingCall(f=None) def _wait_for_boot(): @@ -437,6 +439,10 @@ class VMOps(object): return 'http://fakeajaxconsole/fake_url' def reset_network(self, instance): + """ + Creates uuid arg to pass to make_agent_call and calls it. + + """ args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', instance, '', args) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index 07c7e4df9..f99ea4082 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -94,7 +94,7 @@ def password(self, arg_dict): @jsonify def resetnetwork(self, arg_dict): """ - writes a resquest to xenstore that tells the agent to reset the networking + Writes a resquest to xenstore that tells the agent to reset networking. """ arg_dict['value'] = json.dumps({'name': 'resetnetwork', 'value': ''}) -- cgit From c2f585952a67aa0c922d7ec80b387e8617587541 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 17 Feb 2011 21:27:48 +0100 Subject: Re-alphabetise Authors, move extra addressses into .mailmap. --- .mailmap | 46 ++++++++++++++++++++++++++-------------------- Authors | 10 +++++----- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/.mailmap b/.mailmap index a05520884..a839eba6c 100644 --- a/.mailmap +++ b/.mailmap @@ -1,37 +1,43 @@ # Format is: -# - - +# +# + + + + - - + + + + + + - - - - + - + Masumoto + + + - + + + + - + + + + - - - - - - - - + diff --git a/Authors b/Authors index 395c6b9ed..494e614a0 100644 --- a/Authors +++ b/Authors @@ -3,17 +3,17 @@ Anne Gentle Anthony Young Antony Messerli Armando Migliaccio -Brian Waldon Bilal Akhtar Brian Lamar -Brian Schott +Brian Schott +Brian Waldon Chiradeep Vittal Chmouel Boudjnah Chris Behrens Christian Berendt Cory Wright -David Pravec Dan Prince +David Pravec Dean Troyer Devin Carlen Ed Leafe @@ -44,7 +44,7 @@ Monsyne Dragon Monty Taylor MORITA Kazutaka Muneyuki Noguchi -Nachi Ueno +Nachi Ueno Naveed Massjouni Paul Voccio Ricardo Carrillo Cruz @@ -59,7 +59,7 @@ Soren Hansen Thierry Carrez Todd Willey Trey Morris -Tushar Patil +Tushar Patil Vasiliy Shlykov Vishvananda Ishaya Youcef Laribi -- cgit From e3f461b3b1087fa6342942daa764ba6ffb9ae383 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 17 Feb 2011 22:47:02 +0100 Subject: Add **kwargs to VlanManager's create_networks so that optional args from other managers don't break. --- nova/network/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index b906a83ed..6647692ca 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -509,7 +509,7 @@ class VlanManager(NetworkManager): network_ref['bridge']) def create_networks(self, context, cidr, num_networks, network_size, - cidr_v6, vlan_start, vpn_start): + cidr_v6, vlan_start, vpn_start, **kwargs): """Create networks based on parameters.""" # Check that num_networks + vlan_start is not > 4094, fixes lp708025 if num_networks + vlan_start > 4094: -- cgit From 60ed73265a52f264021bb7452cde9f83181b3dfc Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Feb 2011 17:51:24 -0400 Subject: copyright notice --- nova/api/openstack/servers.py | 2 -- nova/db/sqlalchemy/migrate_repo/versions/004_add_zone_tables.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index c7f863764..009ef6db1 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -1,5 +1,3 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - # Copyright 2010 OpenStack LLC. # All Rights Reserved. # diff --git a/nova/db/sqlalchemy/migrate_repo/versions/004_add_zone_tables.py b/nova/db/sqlalchemy/migrate_repo/versions/004_add_zone_tables.py index d2b6b9570..ade981687 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/004_add_zone_tables.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/004_add_zone_tables.py @@ -1,5 +1,4 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. +# Copyright 2010 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may -- cgit From f6f0135bb320de3cde093f48cb3189380c173b12 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 17 Feb 2011 14:14:07 -0800 Subject: Correctly pass the associate paramater to project_get_network --- nova/db/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/api.py b/nova/db/api.py index 52c2bb84d..d7f3746d2 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -576,7 +576,7 @@ def project_get_network(context, project_id, associate=True): """ - return IMPL.project_get_network(context, project_id) + return IMPL.project_get_network(context, project_id, associate) def project_get_network_v6(context, project_id): -- cgit From fe576e28a6ed8e15d4cdb96313d9f58426715bb0 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 17 Feb 2011 14:39:36 -0800 Subject: move periodic tasks to base class based on class variable as per review --- nova/network/manager.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index a4a4c6064..78b7f0ae1 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -110,6 +110,7 @@ class NetworkManager(manager.Manager): This class must be subclassed to support specific topologies. """ + timeout_fixed_ips = True def __init__(self, network_driver=None, *args, **kwargs): if not network_driver: @@ -138,6 +139,19 @@ class NetworkManager(manager.Manager): self.driver.ensure_floating_forward(floating_ip['address'], fixed_address) + def periodic_tasks(self, context=None): + """Tasks to be run at a periodic interval.""" + super(NetworkManager, self).periodic_tasks(context) + if self.timeout_fixed_ips: + now = utils.utcnow() + timeout = FLAGS.fixed_ip_disassociate_timeout + time = now - datetime.timedelta(seconds=timeout) + num = self.db.fixed_ip_disassociate_all_by_timeout(context, + self.host, + time) + if num: + LOG.debug(_("Dissassociated %s stale fixed ip(s)"), num) + def set_network_host(self, context, network_id): """Safely sets the host of the network.""" LOG.debug(_("setting network host"), context=context) @@ -306,6 +320,7 @@ class FlatManager(NetworkManager): not do any setup in this mode, it must be done manually. Requests to 169.254.169.254 port 80 will need to be forwarded to the api server. """ + timeout_fixed_ips = False def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): """Gets a fixed ip from the pool.""" @@ -397,14 +412,7 @@ class FlatDHCPManager(FlatManager): def periodic_tasks(self, context=None): """Tasks to be run at a periodic interval.""" super(FlatDHCPManager, self).periodic_tasks(context) - now = datetime.datetime.utcnow() - timeout = FLAGS.fixed_ip_disassociate_timeout - time = now - datetime.timedelta(seconds=timeout) - num = self.db.fixed_ip_disassociate_all_by_timeout(context, - self.host, - time) - if num: - LOG.debug(_("Dissassociated %s stale fixed ip(s)"), num) + self._disassociate_old_ips(context) def init_host(self): """Do any initialization that needs to be run if this is a @@ -463,18 +471,6 @@ class VlanManager(NetworkManager): instances in its subnet. """ - def periodic_tasks(self, context=None): - """Tasks to be run at a periodic interval.""" - super(VlanManager, self).periodic_tasks(context) - now = datetime.datetime.utcnow() - timeout = FLAGS.fixed_ip_disassociate_timeout - time = now - datetime.timedelta(seconds=timeout) - num = self.db.fixed_ip_disassociate_all_by_timeout(context, - self.host, - time) - if num: - LOG.debug(_("Dissassociated %s stale fixed ip(s)"), num) - def init_host(self): """Do any initialization that needs to be run if this is a standalone service. -- cgit From eef994eb690a9454e187a2b0cdbde85aba4c55cd Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 17 Feb 2011 14:50:29 -0800 Subject: remove leftover periodic tasks --- nova/network/manager.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index 78b7f0ae1..9f37d966a 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -409,11 +409,6 @@ class FlatDHCPManager(FlatManager): like FlatDHCPManager. """ - def periodic_tasks(self, context=None): - """Tasks to be run at a periodic interval.""" - super(FlatDHCPManager, self).periodic_tasks(context) - self._disassociate_old_ips(context) - def init_host(self): """Do any initialization that needs to be run if this is a standalone service. -- cgit