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 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 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 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 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 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 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 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 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