From 85fe11e11a6332f95a9dac300994e77e7e48dfec Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 31 Jan 2011 14:38:45 -0800 Subject: change ensure_bridge so it doesn't overwrite existing ips --- nova/network/linux_net.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index cdd1f666a..87eefa8b2 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -191,18 +191,19 @@ def ensure_bridge(bridge, interface, net_attrs=None): _execute("sudo brctl stp %s off" % bridge) if interface: _execute("sudo brctl addif %s %s" % (bridge, interface)) + _execute("sudo ifconfig %s up" % bridge) if net_attrs: - _execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \ - (bridge, - net_attrs['gateway'], + # NOTE(vish): use ip addr add so it doesn't overwrite + # manual addresses on the bridge. + suffix = net_attrs['cidr'].rpartition('/')[0] + _execute("sudo ip addr add %s/%s brd %s dev %s" % + (net_attrs['gateway'], + suffix, net_attrs['broadcast'], - net_attrs['netmask'])) + bridge)) if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) - _execute("sudo ifconfig %s up" % bridge) - else: - _execute("sudo ifconfig %s up" % bridge) if FLAGS.use_nova_chains: (out, err) = _execute("sudo iptables -N nova_forward", check_exit_code=False) -- cgit From e4356ceab8b2627dda0b02c7ebbba6d033129360 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 31 Jan 2011 14:43:33 -0800 Subject: rpartition sticks the rhs in [2] --- 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 87eefa8b2..db3ecc7f9 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -195,7 +195,7 @@ def ensure_bridge(bridge, interface, net_attrs=None): if net_attrs: # NOTE(vish): use ip addr add so it doesn't overwrite # manual addresses on the bridge. - suffix = net_attrs['cidr'].rpartition('/')[0] + suffix = net_attrs['cidr'].rpartition('/')[2] _execute("sudo ip addr add %s/%s brd %s dev %s" % (net_attrs['gateway'], suffix, -- cgit From 48a0e252be8b001705db98de8143e1c1ad6294ad Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 1 Feb 2011 17:55:14 -0800 Subject: better setup for flatdhcp --- nova/network/linux_net.py | 40 +++++++++++++++++++++++++++++++++------- nova/network/manager.py | 10 ++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index db3ecc7f9..1a63b759f 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -20,6 +20,7 @@ Implements vlans, bridges, and iptables rules using linux utilities. import os from nova import db +from nova import exception from nova import flags from nova import log as logging from nova import utils @@ -164,7 +165,7 @@ def remove_floating_forward(floating_ip, fixed_ip): % (fixed_ip, floating_ip)) -def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): +def ensure_vlan_bridge(vlan_num, bridge, net_attrs, set_ip=False): """Create a vlan and bridge unless they already exist""" interface = ensure_vlan(vlan_num) ensure_bridge(bridge, interface, net_attrs) @@ -181,7 +182,7 @@ def ensure_vlan(vlan_num): return interface -def ensure_bridge(bridge, interface, net_attrs=None): +def ensure_bridge(bridge, interface, net_attrs, set_ip=False): """Create a bridge unless it already exists""" if not _device_exists(bridge): LOG.debug(_("Starting Bridge interface for %s"), interface) @@ -189,12 +190,10 @@ def ensure_bridge(bridge, interface, net_attrs=None): _execute("sudo brctl setfd %s 0" % bridge) # _execute("sudo brctl setageing %s 10" % bridge) _execute("sudo brctl stp %s off" % bridge) - if interface: - _execute("sudo brctl addif %s %s" % (bridge, interface)) _execute("sudo ifconfig %s up" % bridge) - if net_attrs: - # NOTE(vish): use ip addr add so it doesn't overwrite - # manual addresses on the bridge. + if set_ip: + # NOTE(vish): The ip for dnsmasq has to be the first address on the + # bridge for it to respond to reqests properly suffix = net_attrs['cidr'].rpartition('/')[2] _execute("sudo ip addr add %s/%s brd %s dev %s" % (net_attrs['gateway'], @@ -204,6 +203,33 @@ def ensure_bridge(bridge, interface, net_attrs=None): if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) + else: + # NOTE(vish): if we don't give an ip to the bridge, we set up a route + # for the guests + out, err = _execute("sudo route add -net %s dev %s" % + (net_attrs['cidr'], bridge), + check_exit_code=False) + if err and err != "SIOCADDRT: File exists\n": + raise exception.Error("Failed to add route: %s" % err) + if interface: + # NOTE(vish): This will break if there is already an ip on the + # interface, so we move any ips to the bridge + out, err = _execute("sudo ip addr show dev %s scope global" % + interface) + for line in out.split("\n"): + fields = line.split() + if fields and fields[0] == "inet": + params = ' '.join(fields[1:-2]) + _execute("sudo ip addr del %s dev %s" % (params, fields[-1])) + _execute("sudo ip addr add %s dev %s" % (params, bridge)) + out, err = _execute("sudo brctl addif %s %s" % + (bridge, interface), + check_exit_code=False) + + if (err and err != "device %s is already a member of a bridge; can't " + "enslave it to bridge %s.\n" % (interface, bridge)): + raise exception.Error("Failed to add interface: %s" % err) + if FLAGS.use_nova_chains: (out, err) = _execute("sudo iptables -N nova_forward", check_exit_code=False) diff --git a/nova/network/manager.py b/nova/network/manager.py index fbcbea131..735327230 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -402,7 +402,8 @@ class FlatDHCPManager(FlatManager): """Sets up matching network for compute hosts.""" network_ref = db.network_get_by_instance(context, instance_id) self.driver.ensure_bridge(network_ref['bridge'], - FLAGS.flat_interface) + FLAGS.flat_interface, + network_ref) def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): """Setup dhcp for this network.""" @@ -427,7 +428,7 @@ class FlatDHCPManager(FlatManager): network_ref = db.network_get(context, network_id) self.driver.ensure_bridge(network_ref['bridge'], FLAGS.flat_interface, - network_ref) + network_ref, True) if not FLAGS.fake_network: self.driver.update_dhcp(context, network_id) if(FLAGS.use_ipv6): @@ -498,7 +499,8 @@ class VlanManager(NetworkManager): """Sets up matching network for compute hosts.""" network_ref = db.network_get_by_instance(context, instance_id) self.driver.ensure_vlan_bridge(network_ref['vlan'], - network_ref['bridge']) + network_ref['bridge'], + network_ref) def create_networks(self, context, cidr, num_networks, network_size, cidr_v6, vlan_start, vpn_start): @@ -565,7 +567,7 @@ class VlanManager(NetworkManager): address = network_ref['vpn_public_address'] self.driver.ensure_vlan_bridge(network_ref['vlan'], network_ref['bridge'], - network_ref) + network_ref, True) # NOTE(vish): only ensure this forward if the address hasn't been set # manually. -- cgit From 08794dba04c3919f9abbbfea1615b651394e5ee8 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 1 Feb 2011 18:42:12 -0800 Subject: don't fail on ip add exists and recreate default route on ip move if needed --- nova/network/linux_net.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 1a63b759f..efeed5bc7 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -195,11 +195,14 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): # NOTE(vish): The ip for dnsmasq has to be the first address on the # bridge for it to respond to reqests properly suffix = net_attrs['cidr'].rpartition('/')[2] - _execute("sudo ip addr add %s/%s brd %s dev %s" % - (net_attrs['gateway'], - suffix, - net_attrs['broadcast'], - bridge)) + out, err = _execute("sudo ip addr add %s/%s brd %s dev %s" % + (net_attrs['gateway'], + suffix, + net_attrs['broadcast'], + bridge), + check_exit_code=False) + if err and err != "RTNETLINK answers: File exists\n": + raise exception.Error("Failed to add ip: %s" % err) if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) @@ -214,14 +217,22 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): if interface: # NOTE(vish): This will break if there is already an ip on the # interface, so we move any ips to the bridge + gateway = None + out, err = _execute("sudo route") + for line in out.split("\n"): + fields = line.split() + if fields and fields[0] == "default" and fields[-1] == interface: + gateway = fields[1] out, err = _execute("sudo ip addr show dev %s scope global" % interface) for line in out.split("\n"): fields = line.split() if fields and fields[0] == "inet": - params = ' '.join(fields[1:-2]) + params = ' '.join(fields[1:-1]) _execute("sudo ip addr del %s dev %s" % (params, fields[-1])) _execute("sudo ip addr add %s dev %s" % (params, bridge)) + if gateway: + _execute("sudo route add default gw %s" % gateway) out, err = _execute("sudo brctl addif %s %s" % (bridge, interface), check_exit_code=False) -- cgit From d647a067acb884ff2c324afa5a962a8dae71c6c6 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 1 Feb 2011 19:31:43 -0800 Subject: pass the set_ip from ensure_vlan_bridge --- 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 efeed5bc7..c5cf761f2 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -168,7 +168,7 @@ def remove_floating_forward(floating_ip, fixed_ip): def ensure_vlan_bridge(vlan_num, bridge, net_attrs, set_ip=False): """Create a vlan and bridge unless they already exist""" interface = ensure_vlan(vlan_num) - ensure_bridge(bridge, interface, net_attrs) + ensure_bridge(bridge, interface, net_attrs, set_ip) def ensure_vlan(vlan_num): -- cgit From ef9217548b1ae74d3e4f7282d26e0d9fee5470ce Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 2 Feb 2011 08:15:57 -0800 Subject: moves driver.init_host into the base class so it happens before floating forwards and sets up proper iptables chains --- nova/network/manager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index fbcbea131..8eb9f041b 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -118,6 +118,10 @@ class NetworkManager(manager.Manager): super(NetworkManager, self).__init__(*args, **kwargs) def init_host(self): + """Do any initialization that needs to be run if this is a + standalone service. + """ + self.driver.init_host() # Set up networking for the projects for which we're already # the designated network host. ctxt = context.get_admin_context() @@ -395,7 +399,6 @@ class FlatDHCPManager(FlatManager): standalone service. """ super(FlatDHCPManager, self).init_host() - self.driver.init_host() self.driver.metadata_forward() def setup_compute_network(self, context, instance_id): @@ -465,7 +468,6 @@ class VlanManager(NetworkManager): standalone service. """ super(VlanManager, self).init_host() - self.driver.init_host() self.driver.metadata_forward() def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): -- cgit From 321f581660aad3fc9da5f88276bfdf11f6960d97 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 3 Feb 2011 13:10:19 -0800 Subject: Don't need a route for guests. Turns out the issue with routing from the guests was due to duplicate macs --- nova/network/linux_net.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index c5cf761f2..3a8bd9435 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -206,14 +206,6 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) - else: - # NOTE(vish): if we don't give an ip to the bridge, we set up a route - # for the guests - out, err = _execute("sudo route add -net %s dev %s" % - (net_attrs['cidr'], bridge), - check_exit_code=False) - if err and err != "SIOCADDRT: File exists\n": - raise exception.Error("Failed to add route: %s" % err) if interface: # NOTE(vish): This will break if there is already an ip on the # interface, so we move any ips to the bridge -- cgit From 62d2a1a101dc97e80cb0a582197a6b7468abf593 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 4 Feb 2011 11:04:55 -0600 Subject: Implementation of 'SAN' volumes A SAN volume is 'special' because the volume service probably won't run on the iSCSI target. Initial support is for Solaris with COMSTAR (Solaris 11) --- nova/volume/driver.py | 10 +- nova/volume/manager.py | 2 +- nova/volume/san.py | 373 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+), 6 deletions(-) create mode 100644 nova/volume/san.py diff --git a/nova/volume/driver.py b/nova/volume/driver.py index da7307733..82f4c2f54 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -294,8 +294,10 @@ class ISCSIDriver(VolumeDriver): self._execute("sudo ietadm --op delete --tid=%s" % iscsi_target) - def _get_name_and_portal(self, volume_name, host): + def _get_name_and_portal(self, volume): """Gets iscsi name and portal from volume name and host.""" + volume_name = volume['name'] + host = volume['host'] (out, _err) = self._execute("sudo iscsiadm -m discovery -t " "sendtargets -p %s" % host) for target in out.splitlines(): @@ -307,8 +309,7 @@ class ISCSIDriver(VolumeDriver): def discover_volume(self, volume): """Discover volume on a remote host.""" - iscsi_name, iscsi_portal = self._get_name_and_portal(volume['name'], - volume['host']) + iscsi_name, iscsi_portal = self._get_name_and_portal(volume) self._execute("sudo iscsiadm -m node -T %s -p %s --login" % (iscsi_name, iscsi_portal)) self._execute("sudo iscsiadm -m node -T %s -p %s --op update " @@ -319,8 +320,7 @@ class ISCSIDriver(VolumeDriver): def undiscover_volume(self, volume): """Undiscover volume on a remote host.""" - iscsi_name, iscsi_portal = self._get_name_and_portal(volume['name'], - volume['host']) + iscsi_name, iscsi_portal = self._get_name_and_portal(volume) self._execute("sudo iscsiadm -m node -T %s -p %s --op update " "-n node.startup -v manual" % (iscsi_name, iscsi_portal)) diff --git a/nova/volume/manager.py b/nova/volume/manager.py index 6f8e25e19..6e70ec881 100644 --- a/nova/volume/manager.py +++ b/nova/volume/manager.py @@ -87,7 +87,7 @@ class VolumeManager(manager.Manager): if volume['status'] in ['available', 'in-use']: self.driver.ensure_export(ctxt, volume) else: - LOG.info(_("volume %s: skipping export"), volume_ref['name']) + LOG.info(_("volume %s: skipping export"), volume['name']) def create_volume(self, context, volume_id): """Creates and exports the volume.""" diff --git a/nova/volume/san.py b/nova/volume/san.py new file mode 100644 index 000000000..22a0da13f --- /dev/null +++ b/nova/volume/san.py @@ -0,0 +1,373 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# 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. +""" +Drivers for san-stored volumes. +The unique thing about a SAN is that we don't expect that we can run the volume + controller on the SAN hardware. We expect to access it over SSH or some API. +""" + +import os +import paramiko + +from nova import exception +from nova import flags +from nova import log as logging +from nova.volume.driver import ISCSIDriver + +LOG = logging.getLogger("nova.volume.driver") +FLAGS = flags.FLAGS +flags.DEFINE_boolean('san_thin_provision', 'true', + 'Use thin provisioning for SAN volumes?') +flags.DEFINE_string('san_ip', '', + 'IP address of SAN controller') +flags.DEFINE_string('san_login', 'admin', + 'Username for SAN controller') +flags.DEFINE_string('san_password', '', + 'Password for SAN controller') +flags.DEFINE_string('san_cluster_name', '', + 'Cluster name for creating SAN volumes') +flags.DEFINE_string('san_privatekey', '', + 'Filename of private key to use for SSH authentication') + +class SanISCSIDriver(ISCSIDriver): + """ Base class for SAN-style storage volumes + (storage providers we access over SSH)""" + #Override because SAN ip != host ip + def _get_name_and_portal(self, volume): + """Gets iscsi name and portal from volume name and host.""" + volume_name = volume['name'] + + # TODO(justinsb): store in volume, remerge with generic iSCSI code + host = FLAGS.san_ip + + (out, _err) = self._execute("sudo iscsiadm -m discovery -t " + "sendtargets -p %s" % host) + + location = None + find_iscsi_name = self._build_iscsi_target_name(volume) + for target in out.splitlines(): + if find_iscsi_name in target: + (location, _sep, iscsi_name) = target.partition(" ") + break + if not location: + raise exception.Error(_("Could not find iSCSI export " + " for volume %s") % + volume_name) + + iscsi_portal = location.split(",")[0] + LOG.debug("iscsi_name=%s, iscsi_portal=%s" % (iscsi_name, iscsi_portal)) + return (iscsi_name, iscsi_portal) + + def _build_iscsi_target_name(self, volume): + return "%s%s" % (FLAGS.iscsi_target_prefix, volume['name']) + + # discover_volume is still OK + # undiscover_volume is still OK + + def _connect_to_ssh(self): + ssh = paramiko.SSHClient() + #TODO(justinsb): We need a better SSH key policy + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + if FLAGS.san_password: + ssh.connect(FLAGS.san_ip, + username=FLAGS.san_login, + password=FLAGS.san_password) + elif FLAGS.san_privatekey: + privatekeyfile = os.path.expanduser(FLAGS.san_privatekey) + # It sucks that paramiko doesn't support DSA keys + privatekey = paramiko.RSAKey.from_private_key_file(privatekeyfile) + ssh.connect(FLAGS.san_ip, username=FLAGS.san_login, pkey=privatekey) + else: + raise exception.Error("Specify san_password or san_privatekey") + return ssh + + def _run_ssh(self, command, check_exit_code=True): + #TODO(justinsb): SSH connection caching (?) + ssh = self._connect_to_ssh() + + #TODO(justinsb): Reintroduce the retry hack + ret = ssh_execute(ssh, command, check_exit_code=check_exit_code) + + ssh.close() + + return ret + + def ensure_export(self, context, volume): + """Synchronously recreates an export for a logical volume.""" + pass + + def create_export(self, context, volume): + """Exports the volume.""" + pass + + def remove_export(self, context, volume): + """Removes an export for a logical volume.""" + pass + + def check_for_setup_error(self): + """Returns an error if prerequisites aren't met""" + if not (FLAGS.san_password or FLAGS.san_privatekey): + raise exception.Error("Specify san_password or san_privatekey") + + if not (FLAGS.san_ip): + raise exception.Error("san_ip must be set") + +def _collect_lines(data): + """ Split lines from data into an array, trimming them """ + matches = [] + for line in data.splitlines(): + match = line.strip() + matches.append(match) + + return matches + +def _get_prefixed_values(data, prefix): + """Collect lines which start with prefix; with trimming""" + matches = [] + for line in data.splitlines(): + line = line.strip() + if line.startswith(prefix): + match = line[len(prefix):] + match = match.strip() + matches.append(match) + + return matches + +class SolarisISCSIDriver(SanISCSIDriver): + """Executes commands relating to Solaris-hosted ISCSI volumes.""" + + #pkg install storage-server SUNWiscsit + #svcadm enable stmf + #zfs allow justinsb create,mount,destroy rpool + #usermod -P'File System Management' justinsb + # I don't know which perms are needed for sbdadm... + #usermod -P'Primary Administrator' justinsb + # svcadm enable -r svc:/network/iscsi/target:default + # pfexec itadm create-tpg e1000g0 10.1.184.98 + # pfexec itadm create-target -t e1000g0 + + def _view_exists(self, luid): + (out, _err) = self._run_ssh("pfexec /usr/sbin/stmfadm list-view -l %s" % + (luid), + check_exit_code=False) + if "no views found" in out: + return False + + if "View Entry:" in out: + return True + + raise exception.Error("Cannot parse list-view output: %s" % (out)) + + def _get_target_groups(self): + """Gets list of target groups from host.""" + (out, _err) = self._run_ssh("pfexec /usr/sbin/stmfadm list-tg") + matches = _get_prefixed_values(out, 'Target group: ') + LOG.debug("target_groups=%s" % matches) + return matches + + def _target_group_exists(self, target_group_name): + return target_group_name not in self._get_target_groups() + + def _get_target_group_members(self, target_group_name): + (out, _err) = self._run_ssh("pfexec /usr/sbin/stmfadm list-tg -v %s" % + (target_group_name)) + matches = _get_prefixed_values(out, 'Member: ') + LOG.debug("members of %s=%s" % (target_group_name, matches)) + return matches + + def _is_target_group_member(self, target_group_name, iscsi_target_name): + return iscsi_target_name in ( + self._get_target_group_members(target_group_name)) + + def _get_iscsi_targets(self): + cmd = ("pfexec /usr/sbin/itadm list-target | " + "awk '{print $1}' | grep -v ^TARGET") + (out, _err) = self._run_ssh(cmd) + matches = _collect_lines(out) + LOG.debug("_get_iscsi_targets=%s" % (matches)) + return matches + + def _iscsi_target_exists(self, iscsi_target_name): + return iscsi_target_name in self._get_iscsi_targets() + + def _build_zfs_poolname(self, volume): + #TODO(justinsb): rpool should be configurable + zfs_poolname = 'rpool/%s' % (volume['name']) + return zfs_poolname + + def create_volume(self, volume): + """Creates a volume.""" + if int(volume['size']) == 0: + sizestr = '100M' + else: + sizestr = '%sG' % volume['size'] + + zfs_poolname = self._build_zfs_poolname(volume) + + thin_provision_arg = '-s' if FLAGS.san_thin_provision else '' + # Create a zfs volume + self._run_ssh("pfexec /usr/sbin/zfs create %s -V %s %s" % + (thin_provision_arg, + sizestr, + zfs_poolname)) + + return { # 'target_ip': FLAGS.san_ip + } + + def _get_luid(self, volume): + zfs_poolname = self._build_zfs_poolname(volume) + + cmd = ("pfexec /usr/sbin/sbdadm list-lu | " + "grep -w %s | awk '{print $1}'" % + (zfs_poolname)) + + (stdout, _stderr) = self._run_ssh(cmd) + + luid = stdout.strip() + return luid + + def _is_lu_created(self, volume): + luid = self._get_luid(volume) + return luid + + def delete_volume(self, volume): + """Deletes a volume.""" + zfs_poolname = self._build_zfs_poolname(volume) + self._run_ssh("pfexec /usr/sbin/zfs destroy %s" % + (zfs_poolname)) + + def local_path(self, volume): + # TODO(justinsb): Is this needed here? + escaped_group = FLAGS.volume_group.replace('-', '--') + escaped_name = volume['name'].replace('-', '--') + return "/dev/mapper/%s-%s" % (escaped_group, escaped_name) + + def ensure_export(self, context, volume): + """Synchronously recreates an export for a logical volume.""" + #TODO(justinsb): On bootup, this is called for every volume. + # It then runs ~5 SSH commands for each volume, + # most of which fetch the same info each time + # This makes initial start stupid-slow + self._do_export(volume, force_create=False) + + def create_export(self, context, volume): + self._do_export(volume, force_create=True) + + def _do_export(self, volume, force_create): + # Create a Logical Unit (LU) backed by the zfs volume + zfs_poolname = self._build_zfs_poolname(volume) + + if force_create or not self._is_lu_created(volume): + cmd = ("pfexec /usr/sbin/sbdadm create-lu /dev/zvol/rdsk/%s" % + (zfs_poolname)) + self._run_ssh(cmd) + + luid = self._get_luid(volume) + iscsi_name = self._build_iscsi_target_name(volume) + target_group_name = 'tg-%s' % volume['name'] + + # The sequence of commands looks like this: + #pfexec stmfadm create-tg tg-vol2 + # Yes, we add it before we create it! + #pfexec stmfadm add-tg-member -g tg-vol2 iqn.2010-10.org.openstack:vol2 + #pfexec itadm create-target -n iqn.2010-10.org.openstack:vol2 + #pfexec stmfadm add-view -t tg-vol2 600144F051E2440000004D4A0F730004 + + # Create a iSCSI target, mapped to just this volume + if force_create or not self._target_group_exists(target_group_name): + self._run_ssh("pfexec /usr/sbin/stmfadm create-tg %s" % + (target_group_name)) + + # Yes, we add the initiatior before we create it! + if force_create or not self._is_target_group_member(target_group_name, + iscsi_name): + self._run_ssh("pfexec /usr/sbin/stmfadm add-tg-member -g %s %s" % + (target_group_name, iscsi_name)) + if force_create or not self._iscsi_target_exists(iscsi_name): + self._run_ssh("pfexec /usr/sbin/itadm create-target -n %s" % + (iscsi_name)) + if force_create or not self._view_exists(luid): + self._run_ssh("pfexec /usr/sbin/stmfadm add-view -t %s %s" % + (target_group_name, luid)) + + def remove_export(self, context, volume): + """Removes an export for a logical volume.""" + + # This is the reverse of _do_export + luid = self._get_luid(volume) + iscsi_name = self._build_iscsi_target_name(volume) + target_group_name = 'tg-%s' % volume['name'] + + if self._view_exists(luid): + self._run_ssh("pfexec /usr/sbin/stmfadm remove-view -l %s -a" % + (luid)) + + if self._iscsi_target_exists(iscsi_name): + self._run_ssh("pfexec /usr/sbin/stmfadm offline-target %s" % + (iscsi_name)) + self._run_ssh("pfexec /usr/sbin/itadm delete-target %s" % + (iscsi_name)) + + # We don't delete the tg-member; we delete the whole tg! + + if self._target_group_exists(target_group_name): + self._run_ssh("pfexec /usr/sbin/stmfadm delete-tg %s" % + (target_group_name)) + + if self._is_lu_created(volume): + self._run_ssh("pfexec /usr/sbin/sbdadm delete-lu %s" % + (luid)) + + +def ssh_execute(ssh, cmd, process_input=None, + addl_env=None, check_exit_code=True): + LOG.debug(_("Running cmd (subprocess): %s"), cmd) + if addl_env: + raise exception.Error("Environment not supported over SSH") + + if process_input: + # This is (probably) fixable if we need it... + raise exception.Error("process_input not supported over SSH") + + stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) + channel = stdout_stream.channel + + #stdin.write('process_input would go here') + #stdin.flush() + + # I'm suspicious of this... + # ...other SSH clients have buffering issues with this approach + stdout = stdout_stream.read() + stderr = stderr_stream.read() + stdin_stream.close() + + exit_status = channel.recv_exit_status() + + # exit_status == -1 if no exit code was returned + if exit_status != -1: + LOG.debug(_("Result was %s") % exit_status) + if check_exit_code and exit_status != 0: + raise exception.ProcessExecutionError(exit_code=exit_status, + stdout=stdout, + stderr=stderr, + cmd=cmd) + + # Removed, although this is workaround is needed in utils.execute: + # (no reason to believe it's needed here!) + # greenthread.sleep(0) + + return (stdout, stderr) -- cgit From 5315d5068c6250ccf71c1aa67e7e0109a0718f2a Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 4 Feb 2011 13:07:17 -0600 Subject: Fixes for Vish & Devin's feedback --- nova/utils.py | 35 +++++++++++++++++++++++++ nova/volume/san.py | 77 +++++++++++++----------------------------------------- 2 files changed, 53 insertions(+), 59 deletions(-) diff --git a/nova/utils.py b/nova/utils.py index 5f5225289..100e26f70 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -152,6 +152,41 @@ def execute(cmd, process_input=None, addl_env=None, check_exit_code=True): return result +def ssh_execute(ssh, cmd, process_input=None, + addl_env=None, check_exit_code=True): + LOG.debug(_("Running cmd (SSH): %s"), cmd) + if addl_env: + raise exception.Error("Environment not supported over SSH") + + if process_input: + # This is (probably) fixable if we need it... + raise exception.Error("process_input not supported over SSH") + + stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) + channel = stdout_stream.channel + + #stdin.write('process_input would go here') + #stdin.flush() + + # NOTE(justinsb): This seems suspicious... + # ...other SSH clients have buffering issues with this approach + stdout = stdout_stream.read() + stderr = stderr_stream.read() + stdin_stream.close() + + exit_status = channel.recv_exit_status() + + # exit_status == -1 if no exit code was returned + if exit_status != -1: + LOG.debug(_("Result was %s") % exit_status) + if check_exit_code and exit_status != 0: + raise exception.ProcessExecutionError(exit_code=exit_status, + stdout=stdout, + stderr=stderr, + cmd=cmd) + + return (stdout, stderr) + def abspath(s): return os.path.join(os.path.dirname(__file__), s) diff --git a/nova/volume/san.py b/nova/volume/san.py index 22a0da13f..1f3417ae5 100644 --- a/nova/volume/san.py +++ b/nova/volume/san.py @@ -26,6 +26,7 @@ import paramiko from nova import exception from nova import flags from nova import log as logging +from nova.utils import ssh_execute from nova.volume.driver import ISCSIDriver LOG = logging.getLogger("nova.volume.driver") @@ -38,8 +39,6 @@ flags.DEFINE_string('san_login', 'admin', 'Username for SAN controller') flags.DEFINE_string('san_password', '', 'Password for SAN controller') -flags.DEFINE_string('san_cluster_name', '', - 'Cluster name for creating SAN volumes') flags.DEFINE_string('san_privatekey', '', 'Filename of private key to use for SSH authentication') @@ -148,17 +147,22 @@ def _get_prefixed_values(data, prefix): return matches class SolarisISCSIDriver(SanISCSIDriver): - """Executes commands relating to Solaris-hosted ISCSI volumes.""" - - #pkg install storage-server SUNWiscsit - #svcadm enable stmf - #zfs allow justinsb create,mount,destroy rpool - #usermod -P'File System Management' justinsb - # I don't know which perms are needed for sbdadm... - #usermod -P'Primary Administrator' justinsb - # svcadm enable -r svc:/network/iscsi/target:default - # pfexec itadm create-tpg e1000g0 10.1.184.98 - # pfexec itadm create-target -t e1000g0 + """Executes commands relating to Solaris-hosted ISCSI volumes. + Basic setup for a Solaris iSCSI server: + pkg install storage-server SUNWiscsit + svcadm enable stmf + svcadm enable -r svc:/network/iscsi/target:default + pfexec itadm create-tpg e1000g0 ${MYIP} + pfexec itadm create-target -t e1000g0 + + Then grant the user that will be logging on lots of permissions. + I'm not sure exactly which though: + zfs allow justinsb create,mount,destroy rpool + usermod -P'File System Management' justinsb + usermod -P'Primary Administrator' justinsb + + Also make sure you can login using san_login & san_password/san_privatekey + """ def _view_exists(self, luid): (out, _err) = self._run_ssh("pfexec /usr/sbin/stmfadm list-view -l %s" % @@ -280,19 +284,13 @@ class SolarisISCSIDriver(SanISCSIDriver): iscsi_name = self._build_iscsi_target_name(volume) target_group_name = 'tg-%s' % volume['name'] - # The sequence of commands looks like this: - #pfexec stmfadm create-tg tg-vol2 - # Yes, we add it before we create it! - #pfexec stmfadm add-tg-member -g tg-vol2 iqn.2010-10.org.openstack:vol2 - #pfexec itadm create-target -n iqn.2010-10.org.openstack:vol2 - #pfexec stmfadm add-view -t tg-vol2 600144F051E2440000004D4A0F730004 - # Create a iSCSI target, mapped to just this volume if force_create or not self._target_group_exists(target_group_name): self._run_ssh("pfexec /usr/sbin/stmfadm create-tg %s" % (target_group_name)) # Yes, we add the initiatior before we create it! + # Otherwise, it complains that the target is already active if force_create or not self._is_target_group_member(target_group_name, iscsi_name): self._run_ssh("pfexec /usr/sbin/stmfadm add-tg-member -g %s %s" % @@ -332,42 +330,3 @@ class SolarisISCSIDriver(SanISCSIDriver): self._run_ssh("pfexec /usr/sbin/sbdadm delete-lu %s" % (luid)) - -def ssh_execute(ssh, cmd, process_input=None, - addl_env=None, check_exit_code=True): - LOG.debug(_("Running cmd (subprocess): %s"), cmd) - if addl_env: - raise exception.Error("Environment not supported over SSH") - - if process_input: - # This is (probably) fixable if we need it... - raise exception.Error("process_input not supported over SSH") - - stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) - channel = stdout_stream.channel - - #stdin.write('process_input would go here') - #stdin.flush() - - # I'm suspicious of this... - # ...other SSH clients have buffering issues with this approach - stdout = stdout_stream.read() - stderr = stderr_stream.read() - stdin_stream.close() - - exit_status = channel.recv_exit_status() - - # exit_status == -1 if no exit code was returned - if exit_status != -1: - LOG.debug(_("Result was %s") % exit_status) - if check_exit_code and exit_status != 0: - raise exception.ProcessExecutionError(exit_code=exit_status, - stdout=stdout, - stderr=stderr, - cmd=cmd) - - # Removed, although this is workaround is needed in utils.execute: - # (no reason to believe it's needed here!) - # greenthread.sleep(0) - - return (stdout, stderr) -- cgit From d86f1af6326d4276e9cbfb3274c211ff3f5629cb Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 4 Feb 2011 17:03:37 -0800 Subject: allow for bridge to be the public interface --- nova/network/linux_net.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 3a8bd9435..69389b333 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -206,6 +206,11 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) + # NOTE(vish): If the public interface is the same as the + # bridge, then the bridge has to be in promiscuous + # to forward packets properly. + if(FLAGS.public_interface == bridge): + _execute("sudo ifconfig %s promisc" % bridge) if interface: # NOTE(vish): This will break if there is already an ip on the # interface, so we move any ips to the bridge -- cgit From 1833ed67ffde756ac1bf1aadbc164a22f7a9b005 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Mon, 7 Feb 2011 10:51:43 +0100 Subject: applied http://launchpadlibrarian.net/63698868/713434.patch --- nova/network/linux_net.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index cdd1f666a..6ed42caae 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -37,6 +37,9 @@ FLAGS = flags.FLAGS flags.DEFINE_string('dhcpbridge_flagfile', '/etc/nova/nova-dhcpbridge.conf', 'location of flagfile for dhcpbridge') +flags.DEFINE_string('dhcp_domain', + 'novalocal', + 'domain to use for building the hostnames') flags.DEFINE_string('networks_path', '$state_path/networks', 'Location to keep network config files') @@ -313,8 +316,9 @@ interface %s def _host_dhcp(fixed_ip_ref): """Return a host string for an address""" instance_ref = fixed_ip_ref['instance'] - return "%s,%s.novalocal,%s" % (instance_ref['mac_address'], + return "%s,%s.%s,%s" % (instance_ref['mac_address'], instance_ref['hostname'], + FLAGS.dhcp_domain, fixed_ip_ref['address']) @@ -359,6 +363,7 @@ def _dnsmasq_cmd(net): ' --strict-order', ' --bind-interfaces', ' --conf-file=', + ' --domain=%s' % FLAGS.dhcp_domain, ' --pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), ' --listen-address=%s' % net['gateway'], ' --except-interface=lo', -- cgit From 26f2f38ef217676292c6cd151664a91fb6c9fd24 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Mon, 7 Feb 2011 11:57:12 +0100 Subject: added myself to the Authors file --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 994a5be9b..27782738f 100644 --- a/Authors +++ b/Authors @@ -6,6 +6,7 @@ Armando Migliaccio Chiradeep Vittal Chmouel Boudjnah Chris Behrens +Christian Berendt Cory Wright David Pravec Dan Prince -- cgit From e12069f79cbf35215eeba5257b2394e9ebde5855 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Mon, 7 Feb 2011 14:29:11 +0100 Subject: replaced all calls to ifconfig with calls to ip --- nova/network/linux_net.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index cdd1f666a..6b8108b14 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -177,7 +177,7 @@ def ensure_vlan(vlan_num): LOG.debug(_("Starting VLAN inteface %s"), interface) _execute("sudo vconfig set_name_type VLAN_PLUS_VID_NO_PAD") _execute("sudo vconfig add %s %s" % (FLAGS.vlan_interface, vlan_num)) - _execute("sudo ifconfig %s up" % interface) + _execute("sudo ip link set %s up" % interface) return interface @@ -192,17 +192,17 @@ def ensure_bridge(bridge, interface, net_attrs=None): if interface: _execute("sudo brctl addif %s %s" % (bridge, interface)) if net_attrs: - _execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \ - (bridge, - net_attrs['gateway'], - net_attrs['broadcast'], - net_attrs['netmask'])) + _execute("sudo ip addr add %s/%s dev %s broadcast %s" % \ + (net_attrs['gateway'], + net_attrs['netmask'], + bridge, + net_attrs['broadcast'])) if(FLAGS.use_ipv6): _execute("sudo ip -f inet6 addr change %s dev %s" % (net_attrs['cidr_v6'], bridge)) - _execute("sudo ifconfig %s up" % bridge) + _execute("sudo ip link set %s up" % bridge) else: - _execute("sudo ifconfig %s up" % bridge) + _execute("sudo ip link set %s up" % bridge) if FLAGS.use_nova_chains: (out, err) = _execute("sudo iptables -N nova_forward", check_exit_code=False) @@ -329,7 +329,8 @@ def _execute(cmd, *args, **kwargs): def _device_exists(device): """Check if ethernet device exists""" - (_out, err) = _execute("ifconfig %s" % device, check_exit_code=False) + (_out, err) = _execute("ip link show dev %s" % device, + check_exit_code=False) return not err -- cgit From e62665a12e0b02ef73562a5d579782972332cbe1 Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Mon, 7 Feb 2011 15:20:16 +0100 Subject: fixed format according to PEP8 --- nova/network/linux_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 6ed42caae..de0e488ae 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -318,7 +318,7 @@ def _host_dhcp(fixed_ip_ref): instance_ref = fixed_ip_ref['instance'] return "%s,%s.%s,%s" % (instance_ref['mac_address'], instance_ref['hostname'], - FLAGS.dhcp_domain, + FLAGS.dhcp_domain, fixed_ip_ref['address']) @@ -363,7 +363,7 @@ def _dnsmasq_cmd(net): ' --strict-order', ' --bind-interfaces', ' --conf-file=', - ' --domain=%s' % FLAGS.dhcp_domain, + ' --domain=%s' % FLAGS.dhcp_domain, ' --pid-file=%s' % _dhcp_file(net['bridge'], 'pid'), ' --listen-address=%s' % net['gateway'], ' --except-interface=lo', -- cgit From 2613d6449fa9f07c5ee1627a3c44895071fb1a59 Mon Sep 17 00:00:00 2001 From: Anne Gentle Date: Mon, 7 Feb 2011 16:32:04 -0600 Subject: Made updates to multinode install doc --- doc/source/adminguide/multi.node.install.rst | 38 ++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/doc/source/adminguide/multi.node.install.rst b/doc/source/adminguide/multi.node.install.rst index f2f25b060..cf518b26a 100644 --- a/doc/source/adminguide/multi.node.install.rst +++ b/doc/source/adminguide/multi.node.install.rst @@ -37,20 +37,22 @@ From a server you intend to use as a cloud controller node, use this command to :: - wget --no-check-certificate https://github.com/dubsquared/OpenStack-NOVA-Installer-Script/raw/master/Nova_CC_Installer_v0.1 + wget --no-check-certificate https://github.com/dubsquared/OpenStack-NOVA-Installer-Script/raw/master/ nova-CC-install-v1.1.sh Ensure you can execute the script by modifying the permissions on the script file. :: - sudo chmod 755 Nova_CC_Installer_v0.1 + sudo chmod 755 nova-CC-install-v1.1.sh :: - sudo ./Nova_CC_Installer_v0.1 + sudo ./nova-CC-install-v1.1.sh -Next, from a server you intend to use as a compute node (doesn't contain the database), install the nova services. Copy the nova.conf from the cloud controller node to the compute node. +Next, from a server you intend to use as a compute node (doesn't contain the database), install the nova services. You can use the nova-NODE-installer.sh script from the above github-hosted project for the compute node installation. + +Copy the nova.conf from the cloud controller node to the compute node. Restart related services:: @@ -247,7 +249,7 @@ Here is an example of what this looks like with real data:: Note: The nova-manage service assumes that the first IP address is your network (like 192.168.0.0), that the 2nd IP is your gateway (192.168.0.1), and that the broadcast is the very last IP in the range you defined (192.168.0.255). If this is not the case you will need to manually edit the sql db 'networks' table.o. -On running this command, entries are made in the 'networks' and 'fixed_ips' table. However, one of the networks listed in the 'networks' table needs to be marked as bridge in order for the code to know that a bridge exists. The Network is marked as bridged automatically based on the type of network manager selected. This is ONLY necessary if you chose FlatManager as your network type. More information can be found at the end of this document discussing setting up the bridge device. +On running the "nova-manage network create" command, entries are made in the 'networks' and 'fixed_ips' table. However, one of the networks listed in the 'networks' table needs to be marked as bridge in order for the code to know that a bridge exists. The Network is marked as bridged automatically based on the type of network manager selected. You only need to mark the network as a bridge if you chose FlatManager as your network type. More information can be found at the end of this document discussing setting up the bridge device. Step 2 - Create Nova certifications @@ -288,9 +290,35 @@ Another common issue is you cannot ping or SSH your instances after issusing the killall dnsmasq service nova-network restart +To avoid issues with KVM and permissions with Nova, run the following commands to ensure we have VM's that are running optimally:: + + chgrp kvm /dev/kvm + chmod g+rwx /dev/kvm + +If you want to use the 10.04 Ubuntu Enterprise Cloud images that are readily available at http://uec-images.ubuntu.com/releases/10.04/release/, you may run into delays with booting. Any server that does not have nova-api running on it needs this iptables entry so that UEC images can get metadata info. On compute nodes, configure the iptables with this next step:: + + # iptables -t nat -A PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination $NOVA_API_IP:8773 + Testing the Installation ```````````````````````` +You can confirm that your compute node is talking to your cloud controller. From the cloud controller, run this database query:: + + mysql -u$MYSQL_USER -p$MYSQL_PASS nova -e 'select * from services;' + +In return, you should see something similar to this:: + +---------------------+---------------------+------------+---------+----+----------+----------------+-----------+--------------+----------+-------------------+ + | created_at | updated_at | deleted_at | deleted | id | host | binary | topic | report_count | disabled | availability_zone | + +---------------------+---------------------+------------+---------+----+----------+----------------+-----------+--------------+----------+-------------------+ + | 2011-01-28 22:52:46 | 2011-02-03 06:55:48 | NULL | 0 | 1 | osdemo02 | nova-network | network | 46064 | 0 | nova | + | 2011-01-28 22:52:48 | 2011-02-03 06:55:57 | NULL | 0 | 2 | osdemo02 | nova-compute | compute | 46056 | 0 | nova | + | 2011-01-28 22:52:52 | 2011-02-03 06:55:50 | NULL | 0 | 3 | osdemo02 | nova-scheduler | scheduler | 46065 | 0 | nova | + | 2011-01-29 23:49:29 | 2011-02-03 06:54:26 | NULL | 0 | 4 | osdemo01 | nova-compute | compute | 37050 | 0 | nova | + | 2011-01-30 23:42:24 | 2011-02-03 06:55:44 | NULL | 0 | 9 | osdemo04 | nova-compute | compute | 28484 | 0 | nova | + | 2011-01-30 21:27:28 | 2011-02-03 06:54:23 | NULL | 0 | 8 | osdemo05 | nova-compute | compute | 29284 | 0 | nova | + +---------------------+---------------------+------------+---------+----+----------+----------------+-----------+--------------+----------+-------------------+ +You can see that 'osdemo0{1,2,4,5} are all running 'nova-compute.' When you start spinning up instances, they will allocate on any node that is running nova-compute from this list. + You can then use `euca2ools` to test some items:: euca-describe-images -- cgit From a6b913dfd1d940cbf435cb9d9c5c6e2716cf5c2a Mon Sep 17 00:00:00 2001 From: Anne Gentle Date: Mon, 7 Feb 2011 16:35:03 -0600 Subject: Another quick fix to multinode install doc --- doc/source/adminguide/multi.node.install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/adminguide/multi.node.install.rst b/doc/source/adminguide/multi.node.install.rst index cf518b26a..c53455e3e 100644 --- a/doc/source/adminguide/multi.node.install.rst +++ b/doc/source/adminguide/multi.node.install.rst @@ -37,7 +37,7 @@ From a server you intend to use as a cloud controller node, use this command to :: - wget --no-check-certificate https://github.com/dubsquared/OpenStack-NOVA-Installer-Script/raw/master/ nova-CC-install-v1.1.sh + wget --no-check-certificate https://github.com/dubsquared/OpenStack-NOVA-Installer-Script/raw/master/nova-CC-install-v1.1.sh Ensure you can execute the script by modifying the permissions on the script file. -- cgit From 15321719332a5b782ba5ac66d85db0eccc98ccba Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Mon, 7 Feb 2011 23:01:57 +0000 Subject: Checking whether the instance id is a list or not before assignment. This is to fix a bug relating to nova/boto. The AWK-SDK libraries pass in a string, not a list. the euca tools pass in a list. --- nova/api/ec2/cloud.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 00d044e95..c80e1168a 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -512,8 +512,11 @@ class CloudController(object): def get_console_output(self, context, instance_id, **kwargs): LOG.audit(_("Get console output for instance %s"), instance_id, context=context) - # instance_id is passed in as a list of instances - ec2_id = instance_id[0] + # instance_id may be passed in as a list of instances + if type(instance_id) == list: + ec2_id = instance_id[0] + else: + ec2_id = instance_id instance_id = ec2_id_to_id(ec2_id) output = self.compute_api.get_console_output( context, instance_id=instance_id) -- cgit From a51d187128def4f44ad06cd0880a3e3b4518e073 Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Tue, 8 Feb 2011 01:00:00 +0000 Subject: Catching all socket errors in _get_my_ip, since any socket error is likely enough to cause a failure in detection. --- nova/flags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/flags.py b/nova/flags.py index 43bc174d2..1d8eba94f 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -208,7 +208,7 @@ def _get_my_ip(): (addr, port) = csock.getsockname() csock.close() return addr - except socket.gaierror as ex: + except socket.error as ex: return "127.0.0.1" -- cgit From 976420e608140e449db5748e57cb18fab74b6d43 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 7 Feb 2011 22:05:45 -0800 Subject: use route -n instead of route to avoid chopped names --- nova/network/linux_net.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 69389b333..b66ca1973 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -215,10 +215,10 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): # NOTE(vish): This will break if there is already an ip on the # interface, so we move any ips to the bridge gateway = None - out, err = _execute("sudo route") + out, err = _execute("sudo route -n") for line in out.split("\n"): fields = line.split() - if fields and fields[0] == "default" and fields[-1] == interface: + if fields and fields[0] == "0.0.0.0" and fields[-1] == interface: gateway = fields[1] out, err = _execute("sudo ip addr show dev %s scope global" % interface) @@ -229,7 +229,7 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): _execute("sudo ip addr del %s dev %s" % (params, fields[-1])) _execute("sudo ip addr add %s dev %s" % (params, bridge)) if gateway: - _execute("sudo route add default gw %s" % gateway) + _execute("sudo route add 0.0.0.0 gw %s" % gateway) out, err = _execute("sudo brctl addif %s %s" % (bridge, interface), check_exit_code=False) -- cgit From 6f30cff7374e91c2920759e13971c0149d96d821 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 8 Feb 2011 10:54:29 -0800 Subject: add docstring and revert set_ip changes as they are unnecessary --- nova/network/linux_net.py | 21 ++++++++++++++++----- nova/network/manager.py | 10 ++++------ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 37993d34a..df54606db 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -168,10 +168,10 @@ def remove_floating_forward(floating_ip, fixed_ip): % (fixed_ip, floating_ip)) -def ensure_vlan_bridge(vlan_num, bridge, net_attrs, set_ip=False): +def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): """Create a vlan and bridge unless they already exist""" interface = ensure_vlan(vlan_num) - ensure_bridge(bridge, interface, net_attrs, set_ip) + ensure_bridge(bridge, interface, net_attrs) def ensure_vlan(vlan_num): @@ -185,8 +185,19 @@ def ensure_vlan(vlan_num): return interface -def ensure_bridge(bridge, interface, net_attrs, set_ip=False): - """Create a bridge unless it already exists""" +def ensure_bridge(bridge, interface, net_attrs=None): + """Create a bridge unless it already exists. + + :param interface: the interface to create the bridge on. + :param net_attrs: dictionary with attributes used to create the bridge. + + If net_attrs is set, it will add the net_attrs['gateway'] to the bridge + using net_attrs['broadcast'] and net_attrs['cidr']. It will also add + the ip_v6 address specified in net_attrs['cidr_v6'] if use_ipv6 is set. + + The code will attempt to move any ips that already exist on the interface + onto the bridge and reset the default gateway if necessary. + """ if not _device_exists(bridge): LOG.debug(_("Starting Bridge interface for %s"), interface) _execute("sudo brctl addbr %s" % bridge) @@ -194,7 +205,7 @@ def ensure_bridge(bridge, interface, net_attrs, set_ip=False): # _execute("sudo brctl setageing %s 10" % bridge) _execute("sudo brctl stp %s off" % bridge) _execute("sudo ip link set %s up" % bridge) - if set_ip: + if net_attrs: # NOTE(vish): The ip for dnsmasq has to be the first address on the # bridge for it to respond to reqests properly suffix = net_attrs['cidr'].rpartition('/')[2] diff --git a/nova/network/manager.py b/nova/network/manager.py index 735327230..fbcbea131 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -402,8 +402,7 @@ class FlatDHCPManager(FlatManager): """Sets up matching network for compute hosts.""" network_ref = db.network_get_by_instance(context, instance_id) self.driver.ensure_bridge(network_ref['bridge'], - FLAGS.flat_interface, - network_ref) + FLAGS.flat_interface) def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): """Setup dhcp for this network.""" @@ -428,7 +427,7 @@ class FlatDHCPManager(FlatManager): network_ref = db.network_get(context, network_id) self.driver.ensure_bridge(network_ref['bridge'], FLAGS.flat_interface, - network_ref, True) + network_ref) if not FLAGS.fake_network: self.driver.update_dhcp(context, network_id) if(FLAGS.use_ipv6): @@ -499,8 +498,7 @@ class VlanManager(NetworkManager): """Sets up matching network for compute hosts.""" network_ref = db.network_get_by_instance(context, instance_id) self.driver.ensure_vlan_bridge(network_ref['vlan'], - network_ref['bridge'], - network_ref) + network_ref['bridge']) def create_networks(self, context, cidr, num_networks, network_size, cidr_v6, vlan_start, vpn_start): @@ -567,7 +565,7 @@ class VlanManager(NetworkManager): address = network_ref['vpn_public_address'] self.driver.ensure_vlan_bridge(network_ref['vlan'], network_ref['bridge'], - network_ref, True) + network_ref) # NOTE(vish): only ensure this forward if the address hasn't been set # manually. -- cgit From d5501234cfc434fbb4b959b63822598a1a68b88b Mon Sep 17 00:00:00 2001 From: Bilal Akhtar Date: Wed, 9 Feb 2011 11:34:23 +0300 Subject: Give a better error message if the instance type specified is invalid. --- nova/compute/instance_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 196d6a8df..510bfd99e 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -38,8 +38,8 @@ def get_by_type(instance_type): if instance_type is None: return FLAGS.default_instance_type if instance_type not in INSTANCE_TYPES: - raise exception.ApiError(_("Unknown instance type: %s"), - instance_type) + raise exception.ApiError(_("Unknown instance type: %s") % (instance_type), + "Invalid") return instance_type -- cgit From fef2b4edaaf77109457dc2bf80e7f845a65a129e Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 9 Feb 2011 13:22:10 +0100 Subject: Don't convert datetime objects to a string using .isoformat(). Leave it to sqlalchmeny (or pysqlite or whatever it is that does the magic) to work it out. --- 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 85250d56e..80c844635 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -579,7 +579,7 @@ def fixed_ip_disassociate_all_by_timeout(_context, host, time): 'AND instance_id IS NOT NULL ' 'AND allocated = 0', {'host': host, - 'time': time.isoformat()}) + 'time': time}) return result.rowcount -- cgit From 96fbbcde9c84a72036a74ba07318f31a471eb402 Mon Sep 17 00:00:00 2001 From: Bilal Akhtar Date: Wed, 9 Feb 2011 17:24:36 +0300 Subject: Add my name to AUTHORS, remove parentheses from the substitution made in the previous commit --- Authors | 1 + nova/compute/instance_types.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Authors b/Authors index 27782738f..b359fec22 100644 --- a/Authors +++ b/Authors @@ -3,6 +3,7 @@ Anne Gentle Anthony Young Antony Messerli Armando Migliaccio +Bilal Akhtar Chiradeep Vittal Chmouel Boudjnah Chris Behrens diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 510bfd99e..a41f5fa79 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -38,7 +38,7 @@ def get_by_type(instance_type): if instance_type is None: return FLAGS.default_instance_type if instance_type not in INSTANCE_TYPES: - raise exception.ApiError(_("Unknown instance type: %s") % (instance_type), + raise exception.ApiError(_("Unknown instance type: %s") % instance_type, "Invalid") return instance_type -- cgit From 636bf106d5fc0424b9045e79ea18fb74406e070c Mon Sep 17 00:00:00 2001 From: SuperStack Date: Wed, 9 Feb 2011 09:49:59 -0800 Subject: Added my mail alias (Part of an experiment in using github, which got messy fast...) --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index d13219ab0..c6f6c9a8b 100644 --- a/.mailmap +++ b/.mailmap @@ -33,3 +33,4 @@ + -- cgit From d4b4fa93e7603d73eb99c8edb0e648ff047cda30 Mon Sep 17 00:00:00 2001 From: SuperStack Date: Wed, 9 Feb 2011 11:18:48 -0800 Subject: Fix PEP8 violations --- nova/utils.py | 1 + nova/volume/san.py | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/nova/utils.py b/nova/utils.py index 100e26f70..8d7ff1f64 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -187,6 +187,7 @@ def ssh_execute(ssh, cmd, process_input=None, return (stdout, stderr) + def abspath(s): return os.path.join(os.path.dirname(__file__), s) diff --git a/nova/volume/san.py b/nova/volume/san.py index 1f3417ae5..e7d559a2a 100644 --- a/nova/volume/san.py +++ b/nova/volume/san.py @@ -42,6 +42,7 @@ flags.DEFINE_string('san_password', '', flags.DEFINE_string('san_privatekey', '', 'Filename of private key to use for SSH authentication') + class SanISCSIDriver(ISCSIDriver): """ Base class for SAN-style storage volumes (storage providers we access over SSH)""" @@ -68,7 +69,8 @@ class SanISCSIDriver(ISCSIDriver): volume_name) iscsi_portal = location.split(",")[0] - LOG.debug("iscsi_name=%s, iscsi_portal=%s" % (iscsi_name, iscsi_portal)) + LOG.debug("iscsi_name=%s, iscsi_portal=%s" % + (iscsi_name, iscsi_portal)) return (iscsi_name, iscsi_portal) def _build_iscsi_target_name(self, volume): @@ -89,7 +91,9 @@ class SanISCSIDriver(ISCSIDriver): privatekeyfile = os.path.expanduser(FLAGS.san_privatekey) # It sucks that paramiko doesn't support DSA keys privatekey = paramiko.RSAKey.from_private_key_file(privatekeyfile) - ssh.connect(FLAGS.san_ip, username=FLAGS.san_login, pkey=privatekey) + ssh.connect(FLAGS.san_ip, + username=FLAGS.san_login, + pkey=privatekey) else: raise exception.Error("Specify san_password or san_privatekey") return ssh @@ -125,6 +129,7 @@ class SanISCSIDriver(ISCSIDriver): if not (FLAGS.san_ip): raise exception.Error("san_ip must be set") + def _collect_lines(data): """ Split lines from data into an array, trimming them """ matches = [] @@ -134,6 +139,7 @@ def _collect_lines(data): return matches + def _get_prefixed_values(data, prefix): """Collect lines which start with prefix; with trimming""" matches = [] @@ -146,6 +152,7 @@ def _get_prefixed_values(data, prefix): return matches + class SolarisISCSIDriver(SanISCSIDriver): """Executes commands relating to Solaris-hosted ISCSI volumes. Basic setup for a Solaris iSCSI server: @@ -165,8 +172,8 @@ class SolarisISCSIDriver(SanISCSIDriver): """ def _view_exists(self, luid): - (out, _err) = self._run_ssh("pfexec /usr/sbin/stmfadm list-view -l %s" % - (luid), + cmd = "pfexec /usr/sbin/stmfadm list-view -l %s" % (luid) + (out, _err) = self._run_ssh(cmd, check_exit_code=False) if "no views found" in out: return False @@ -229,9 +236,6 @@ class SolarisISCSIDriver(SanISCSIDriver): sizestr, zfs_poolname)) - return { # 'target_ip': FLAGS.san_ip - } - def _get_luid(self, volume): zfs_poolname = self._build_zfs_poolname(volume) @@ -329,4 +333,3 @@ class SolarisISCSIDriver(SanISCSIDriver): if self._is_lu_created(volume): self._run_ssh("pfexec /usr/sbin/sbdadm delete-lu %s" % (luid)) - -- cgit From b1fbb1a4a087722ce6dc7fd7a1b9fe01cb6ec766 Mon Sep 17 00:00:00 2001 From: SuperStack Date: Wed, 9 Feb 2011 11:25:18 -0800 Subject: Indent args to ssh_connect correctly --- nova/volume/san.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/volume/san.py b/nova/volume/san.py index e7d559a2a..26d6125e7 100644 --- a/nova/volume/san.py +++ b/nova/volume/san.py @@ -92,8 +92,8 @@ class SanISCSIDriver(ISCSIDriver): # It sucks that paramiko doesn't support DSA keys privatekey = paramiko.RSAKey.from_private_key_file(privatekeyfile) ssh.connect(FLAGS.san_ip, - username=FLAGS.san_login, - pkey=privatekey) + username=FLAGS.san_login, + pkey=privatekey) else: raise exception.Error("Specify san_password or san_privatekey") return ssh -- cgit From 216822bdda290f964020134599749ebbadc76566 Mon Sep 17 00:00:00 2001 From: Bilal Akhtar Date: Thu, 10 Feb 2011 13:08:25 +0300 Subject: Wrap line to under 79 characters --- nova/compute/instance_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index a41f5fa79..309313fd0 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -38,8 +38,8 @@ def get_by_type(instance_type): if instance_type is None: return FLAGS.default_instance_type if instance_type not in INSTANCE_TYPES: - raise exception.ApiError(_("Unknown instance type: %s") % instance_type, - "Invalid") + raise exception.ApiError(_("Unknown instance type: %s") % \ + instance_type, "Invalid") return instance_type -- cgit From 1280c9e97b66b3914c3b7426ef6aeca57e6ff9e4 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 10 Feb 2011 12:49:52 +0100 Subject: Try setting isolation_level=immediate --- nova/db/sqlalchemy/session.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py index dc885f138..2d90dc20f 100644 --- a/nova/db/sqlalchemy/session.py +++ b/nova/db/sqlalchemy/session.py @@ -39,6 +39,7 @@ def get_session(autocommit=True, expire_on_commit=False): if not _ENGINE: _ENGINE = create_engine(FLAGS.sql_connection, pool_recycle=FLAGS.sql_idle_timeout, + isolation_level="immediate", echo=False) _MAKER = (sessionmaker(bind=_ENGINE, autocommit=autocommit, -- cgit From 3e13d005c776b99604d1b8714a79709da1e76467 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 10 Feb 2011 13:23:06 +0100 Subject: Try using NullPool instead of SingletonPool --- nova/db/sqlalchemy/session.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py index 2d90dc20f..5dd72dc08 100644 --- a/nova/db/sqlalchemy/session.py +++ b/nova/db/sqlalchemy/session.py @@ -20,6 +20,7 @@ Session Handling for SQLAlchemy backend """ from sqlalchemy import create_engine +from sqlalchemy import pool from sqlalchemy.orm import sessionmaker from nova import exception @@ -39,7 +40,7 @@ def get_session(autocommit=True, expire_on_commit=False): if not _ENGINE: _ENGINE = create_engine(FLAGS.sql_connection, pool_recycle=FLAGS.sql_idle_timeout, - isolation_level="immediate", + poolclass=pool.NullPool, echo=False) _MAKER = (sessionmaker(bind=_ENGINE, autocommit=autocommit, -- cgit From aff63810b287fdbd0eb6b2e8881dcf6683ed7d91 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 10 Feb 2011 14:31:51 +0100 Subject: Also add floating ip forwarding to OUTPUT chain. --- nova/network/linux_net.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index df54606db..ed37e8ba7 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -156,6 +156,8 @@ def ensure_floating_forward(floating_ip, fixed_ip): """Ensure floating ip forwarding rule""" _confirm_rule("PREROUTING", "-t nat -d %s -j DNAT --to %s" % (floating_ip, fixed_ip)) + _confirm_rule("OUTPUT", "-t nat -d %s -j DNAT --to %s" + % (floating_ip, fixed_ip)) _confirm_rule("SNATTING", "-t nat -s %s -j SNAT --to %s" % (fixed_ip, floating_ip)) @@ -164,6 +166,8 @@ def remove_floating_forward(floating_ip, fixed_ip): """Remove forwarding for floating ip""" _remove_rule("PREROUTING", "-t nat -d %s -j DNAT --to %s" % (floating_ip, fixed_ip)) + _remove_rule("OUTPUT", "-t nat -d %s -j DNAT --to %s" + % (floating_ip, fixed_ip)) _remove_rule("SNATTING", "-t nat -s %s -j SNAT --to %s" % (fixed_ip, floating_ip)) -- cgit From d65d2e2d34bffa2548dabcde2e230da185125026 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 10 Feb 2011 14:37:13 +0100 Subject: Only use NullPool when using sqlite. --- nova/db/sqlalchemy/session.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py index 5dd72dc08..4a9a28f43 100644 --- a/nova/db/sqlalchemy/session.py +++ b/nova/db/sqlalchemy/session.py @@ -38,10 +38,14 @@ def get_session(autocommit=True, expire_on_commit=False): global _MAKER if not _MAKER: if not _ENGINE: + kwargs = {'pool_recycle': FLAGS.sql_idle_timeout, + 'echo': False} + + if FLAGS.sql_connection.startswith('sqlite'): + kwargs['poolclass'] = pool.NullPool + _ENGINE = create_engine(FLAGS.sql_connection, - pool_recycle=FLAGS.sql_idle_timeout, - poolclass=pool.NullPool, - echo=False) + **kwargs) _MAKER = (sessionmaker(bind=_ENGINE, autocommit=autocommit, expire_on_commit=expire_on_commit)) -- cgit From 3f800a8ecde159cb34c5fe358da3aadce660a03a Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 10 Feb 2011 14:56:24 +0100 Subject: Make rpc.cast create a fresh amqp connection. Each API request has its own thread, and they don't multiplex well. --- nova/rpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/rpc.py b/nova/rpc.py index 01fc6d44b..c19ee4635 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -346,7 +346,7 @@ def cast(context, topic, msg): """Sends a message on a topic without waiting for a response""" LOG.debug(_("Making asynchronous cast...")) _pack_context(msg, context) - conn = Connection.instance() + conn = Connection.instance(True) publisher = TopicPublisher(connection=conn, topic=topic) publisher.send(msg) publisher.close() -- cgit From 51b7eb9fd9a56e58137c8be21ea002871bd65e30 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 10 Feb 2011 19:40:21 +0000 Subject: sql_idle_timeout should be an integer --- nova/flags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index 1d8eba94f..3ba3fe6fa 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -286,8 +286,8 @@ DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'), DEFINE_string('sql_connection', 'sqlite:///$state_path/nova.sqlite', 'connection string for sql database') -DEFINE_string('sql_idle_timeout', - '3600', +DEFINE_integer('sql_idle_timeout', + 3600, 'timeout for idle sql database connections') DEFINE_integer('sql_max_retries', 12, 'sql connection attempts') DEFINE_integer('sql_retry_interval', 10, 'sql connection retry interval') -- cgit From c6ad6b53230d1c3ca540a1dcdcd1f3ebf4f31f07 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 11 Feb 2011 12:27:50 +0100 Subject: Create a new AMQP connection by default. --- nova/rpc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nova/rpc.py b/nova/rpc.py index c19ee4635..2b1f7298b 100644 --- a/nova/rpc.py +++ b/nova/rpc.py @@ -46,7 +46,7 @@ LOG = logging.getLogger('nova.rpc') class Connection(carrot_connection.BrokerConnection): """Connection instance object""" @classmethod - def instance(cls, new=False): + def instance(cls, new=True): """Returns the instance""" if new or not hasattr(cls, '_instance'): params = dict(hostname=FLAGS.rabbit_host, @@ -246,7 +246,7 @@ def msg_reply(msg_id, reply=None, failure=None): LOG.error(_("Returning exception %s to caller"), message) LOG.error(tb) failure = (failure[0].__name__, str(failure[1]), tb) - conn = Connection.instance(True) + conn = Connection.instance() publisher = DirectPublisher(connection=conn, msg_id=msg_id) try: publisher.send({'result': reply, 'failure': failure}) @@ -319,7 +319,7 @@ def call(context, topic, msg): self.result = data['result'] wait_msg = WaitMessage() - conn = Connection.instance(True) + conn = Connection.instance() consumer = DirectConsumer(connection=conn, msg_id=msg_id) consumer.register_callback(wait_msg) @@ -346,7 +346,7 @@ def cast(context, topic, msg): """Sends a message on a topic without waiting for a response""" LOG.debug(_("Making asynchronous cast...")) _pack_context(msg, context) - conn = Connection.instance(True) + conn = Connection.instance() publisher = TopicPublisher(connection=conn, topic=topic) publisher.send(msg) publisher.close() -- cgit From d7042ae6bb37a3bff94d0e90535b92a92d7c94f9 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 11 Feb 2011 11:30:56 -0800 Subject: joinedload network so describe_instances continues to work --- nova/db/sqlalchemy/api.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 80c844635..02855e7a9 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -719,6 +719,7 @@ def instance_get_all(context): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(deleted=can_read_deleted(context)).\ all() @@ -729,6 +730,7 @@ def instance_get_all_by_user(context, user_id): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(deleted=can_read_deleted(context)).\ filter_by(user_id=user_id).\ all() @@ -740,6 +742,7 @@ def instance_get_all_by_host(context, host): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(host=host).\ filter_by(deleted=can_read_deleted(context)).\ all() @@ -753,6 +756,7 @@ def instance_get_all_by_project(context, project_id): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(project_id=project_id).\ filter_by(deleted=can_read_deleted(context)).\ all() @@ -766,6 +770,7 @@ def instance_get_all_by_reservation(context, reservation_id): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(reservation_id=reservation_id).\ filter_by(deleted=can_read_deleted(context)).\ all() @@ -773,6 +778,7 @@ def instance_get_all_by_reservation(context, reservation_id): return session.query(models.Instance).\ options(joinedload_all('fixed_ip.floating_ips')).\ options(joinedload('security_groups')).\ + options(joinedload_all('fixed_ip.network')).\ filter_by(project_id=context.project_id).\ filter_by(reservation_id=reservation_id).\ filter_by(deleted=False).\ -- cgit