From 33850cb57e195e538d6e42cb6d10f8296c0d4be4 Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Mon, 25 Oct 2010 22:42:49 +0000 Subject: Moving the openldap schema out of nova.sh into it's own files, and adding sun (opends/opendj/sun directory server/fedora ds) schema files --- nova/auth/nova_openldap.schema | 84 +++++++++++++++++++++++++ nova/auth/nova_sun.schema | 16 +++++ nova/auth/openssh-lpk_openldap.schema | 19 ++++++ nova/auth/openssh-lpk_sun.schema | 3 + nova/auth/slap.sh | 112 +--------------------------------- 5 files changed, 125 insertions(+), 109 deletions(-) create mode 100644 nova/auth/nova_openldap.schema create mode 100644 nova/auth/nova_sun.schema create mode 100644 nova/auth/openssh-lpk_openldap.schema create mode 100644 nova/auth/openssh-lpk_sun.schema diff --git a/nova/auth/nova_openldap.schema b/nova/auth/nova_openldap.schema new file mode 100644 index 000000000..4047361de --- /dev/null +++ b/nova/auth/nova_openldap.schema @@ -0,0 +1,84 @@ +# +# Person object for Nova +# inetorgperson with extra attributes +# Author: Vishvananda Ishaya +# +# + +# using internet experimental oid arc as per BP64 3.1 +objectidentifier novaSchema 1.3.6.1.3.1.666.666 +objectidentifier novaAttrs novaSchema:3 +objectidentifier novaOCs novaSchema:4 + +attributetype ( + novaAttrs:1 + NAME 'accessKey' + DESC 'Key for accessing data' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( + novaAttrs:2 + NAME 'secretKey' + DESC 'Secret key' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( + novaAttrs:3 + NAME 'keyFingerprint' + DESC 'Fingerprint of private key' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + ) + +attributetype ( + novaAttrs:4 + NAME 'isAdmin' + DESC 'Is user an administrator?' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) + +attributetype ( + novaAttrs:5 + NAME 'projectManager' + DESC 'Project Managers of a project' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + ) + +objectClass ( + novaOCs:1 + NAME 'novaUser' + DESC 'access and secret keys' + AUXILIARY + MUST ( uid ) + MAY ( accessKey $ secretKey $ isAdmin ) + ) + +objectClass ( + novaOCs:2 + NAME 'novaKeyPair' + DESC 'Key pair for User' + SUP top + STRUCTURAL + MUST ( cn $ sshPublicKey $ keyFingerprint ) + ) + +objectClass ( + novaOCs:3 + NAME 'novaProject' + DESC 'Container for project' + SUP groupOfNames + STRUCTURAL + MUST ( cn $ projectManager ) + ) diff --git a/nova/auth/nova_sun.schema b/nova/auth/nova_sun.schema new file mode 100644 index 000000000..e925e05e4 --- /dev/null +++ b/nova/auth/nova_sun.schema @@ -0,0 +1,16 @@ +# +# Person object for Nova +# inetorgperson with extra attributes +# Author: Vishvananda Ishaya +# Modified for strict RFC 4512 compatibility by: Ryan Lane +# +# using internet experimental oid arc as per BP64 3.1 +dn: cn=schema +attributeTypes: ( 1.3.6.1.3.1.666.666.3.1 NAME 'accessKey' DESC 'Key for accessing data' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.3.1.666.666.3.2 NAME 'secretKey' DESC 'Secret key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.3.1.666.666.3.3 NAME 'keyFingerprint' DESC 'Fingerprint of private key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE) +attributeTypes: ( 1.3.6.1.3.1.666.666.3.4 NAME 'isAdmin' DESC 'Is user an administrator?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +attributeTypes: ( 1.3.6.1.3.1.666.666.3.5 NAME 'projectManager' DESC 'Project Managers of a project' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +objectClasses: ( 1.3.6.1.3.1.666.666.4.1 NAME 'novaUser' DESC 'access and secret keys' SUP top AUXILIARY MUST ( uid ) MAY ( accessKey $ secretKey $ isAdmin ) ) +objectClasses: ( 1.3.6.1.3.1.666.666.4.2 NAME 'novaKeyPair' DESC 'Key pair for User' SUP top STRUCTURAL MUST ( cn $ sshPublicKey $ keyFingerprint ) ) +objectClasses: ( 1.3.6.1.3.1.666.666.4.3 NAME 'novaProject' DESC 'Container for project' SUP groupOfNames STRUCTURAL MUST ( cn $ projectManager ) ) diff --git a/nova/auth/openssh-lpk_openldap.schema b/nova/auth/openssh-lpk_openldap.schema new file mode 100644 index 000000000..93351da6d --- /dev/null +++ b/nova/auth/openssh-lpk_openldap.schema @@ -0,0 +1,19 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey +# Author: Eric AUGE +# +# Based on the proposal of : Mark Ruijter +# + + +# octetString SYNTAX +attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' + DESC 'MANDATORY: OpenSSH Public key' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + +# printableString SYNTAX yes|no +objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY + DESC 'MANDATORY: OpenSSH LPK objectclass' + MAY ( sshPublicKey $ uid ) + ) diff --git a/nova/auth/openssh-lpk_sun.schema b/nova/auth/openssh-lpk_sun.schema new file mode 100644 index 000000000..5b220ab06 --- /dev/null +++ b/nova/auth/openssh-lpk_sun.schema @@ -0,0 +1,3 @@ +dn: cn=schema +attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) ) diff --git a/nova/auth/slap.sh b/nova/auth/slap.sh index fdc0e39dc..797675d2e 100755 --- a/nova/auth/slap.sh +++ b/nova/auth/slap.sh @@ -20,115 +20,9 @@ apt-get install -y slapd ldap-utils python-ldap -cat >/etc/ldap/schema/openssh-lpk_openldap.schema < -# -# Based on the proposal of : Mark Ruijter -# - - -# octetString SYNTAX -attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' - DESC 'MANDATORY: OpenSSH Public key' - EQUALITY octetStringMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) - -# printableString SYNTAX yes|no -objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY - DESC 'MANDATORY: OpenSSH LPK objectclass' - MAY ( sshPublicKey $ uid ) - ) -LPK_SCHEMA_EOF - -cat >/etc/ldap/schema/nova.schema < -# -# - -# using internet experimental oid arc as per BP64 3.1 -objectidentifier novaSchema 1.3.6.1.3.1.666.666 -objectidentifier novaAttrs novaSchema:3 -objectidentifier novaOCs novaSchema:4 - -attributetype ( - novaAttrs:1 - NAME 'accessKey' - DESC 'Key for accessing data' - EQUALITY caseIgnoreMatch - SUBSTR caseIgnoreSubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 - SINGLE-VALUE - ) - -attributetype ( - novaAttrs:2 - NAME 'secretKey' - DESC 'Secret key' - EQUALITY caseIgnoreMatch - SUBSTR caseIgnoreSubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 - SINGLE-VALUE - ) - -attributetype ( - novaAttrs:3 - NAME 'keyFingerprint' - DESC 'Fingerprint of private key' - EQUALITY caseIgnoreMatch - SUBSTR caseIgnoreSubstringsMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 - SINGLE-VALUE - ) - -attributetype ( - novaAttrs:4 - NAME 'isAdmin' - DESC 'Is user an administrator?' - EQUALITY booleanMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 - SINGLE-VALUE - ) - -attributetype ( - novaAttrs:5 - NAME 'projectManager' - DESC 'Project Managers of a project' - SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 - ) - -objectClass ( - novaOCs:1 - NAME 'novaUser' - DESC 'access and secret keys' - AUXILIARY - MUST ( uid ) - MAY ( accessKey $ secretKey $ isAdmin ) - ) - -objectClass ( - novaOCs:2 - NAME 'novaKeyPair' - DESC 'Key pair for User' - SUP top - STRUCTURAL - MUST ( cn $ sshPublicKey $ keyFingerprint ) - ) - -objectClass ( - novaOCs:3 - NAME 'novaProject' - DESC 'Container for project' - SUP groupOfNames - STRUCTURAL - MUST ( cn $ projectManager ) - ) - -NOVA_SCHEMA_EOF +abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"` +cp $abspath/openssh-lpk_openldap.schema /etc/ldap/schema/openssh-lpk_openldap.schema +cp $abspath/nova_openldap.schema /etc/ldap/schema/nova_openldap.schema mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf.orig cat >/etc/ldap/slapd.conf < Date: Mon, 25 Oct 2010 22:50:32 +0000 Subject: Documentation was missing; added --- nova/auth/openssh-lpk_sun.schema | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nova/auth/openssh-lpk_sun.schema b/nova/auth/openssh-lpk_sun.schema index 5b220ab06..5f52db3b6 100644 --- a/nova/auth/openssh-lpk_sun.schema +++ b/nova/auth/openssh-lpk_sun.schema @@ -1,3 +1,10 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey +# Author: Eric AUGE +# +# Schema for Sun Directory Server. +# Based on the original schema, modified by Stefan Fischer. +# dn: cn=schema attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) ) -- cgit From b65b41e5957d5ded516343b3611292c9744d169f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 4 Nov 2010 12:42:14 +0100 Subject: Add a templating mechanism in the flag parsing. Add a state_path flag that will be used as the top-level dir for all other state (such as images, instances, buckets, networks, etc). This way you only need to change one flag to put all your state in e.g. /var/lib/nova. --- nova/compute/manager.py | 2 +- nova/compute/monitor.py | 2 +- nova/crypto.py | 4 ++-- nova/flags.py | 22 ++++++++++++++++++++-- nova/network/linux_net.py | 2 +- nova/objectstore/bucket.py | 2 +- nova/objectstore/image.py | 4 ++-- 7 files changed, 28 insertions(+), 10 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 850cded8a..65fa50431 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -33,7 +33,7 @@ from nova.compute import power_state FLAGS = flags.FLAGS -flags.DEFINE_string('instances_path', utils.abspath('../instances'), +flags.DEFINE_string('instances_path', '$state_path/instances', 'where instances are stored on disk') flags.DEFINE_string('compute_driver', 'nova.virt.connection.get_connection', 'Driver to use for volume creation') diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py index d0154600f..024f3ed3c 100644 --- a/nova/compute/monitor.py +++ b/nova/compute/monitor.py @@ -46,7 +46,7 @@ flags.DEFINE_integer('monitoring_instances_delay', 5, 'Sleep time between updates') flags.DEFINE_integer('monitoring_instances_step', 300, 'Interval of RRD updates') -flags.DEFINE_string('monitoring_rrd_path', '/var/nova/monitor/instances', +flags.DEFINE_string('monitoring_rrd_path', '$state_path/monitor/instances', 'Location of RRD files') diff --git a/nova/crypto.py b/nova/crypto.py index 16b4f5e1f..045f7f53f 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -39,9 +39,9 @@ from nova import flags FLAGS = flags.FLAGS flags.DEFINE_string('ca_file', 'cacert.pem', 'Filename of root CA') -flags.DEFINE_string('keys_path', utils.abspath('../keys'), +flags.DEFINE_string('keys_path', '$state_path/keys', 'Where we keep our keys') -flags.DEFINE_string('ca_path', utils.abspath('../CA'), +flags.DEFINE_string('ca_path', '$state_path/CA', 'Where we keep our root CA') flags.DEFINE_boolean('use_intermediate_ca', False, 'Should we use intermediate CAs for each project?') diff --git a/nova/flags.py b/nova/flags.py index 4ae86d9b2..2b8bbbdb7 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -26,6 +26,8 @@ import os import socket import sys +from string import Template + import gflags @@ -134,8 +136,21 @@ class FlagValues(gflags.FlagValues): def __getattr__(self, name): if self.IsDirty(name): self.ParseNewFlags() - return gflags.FlagValues.__getattr__(self, name) + val = gflags.FlagValues.__getattr__(self, name) + if type(val) is str: + tmpl = Template(val) + return tmpl.substitute(StrWrapper(self)) + return val +class StrWrapper(object): + def __init__(self, obj): + self.wrapped = obj + + def __getitem__(self, name): + if hasattr(self.wrapped, name): + return str(getattr(self.wrapped, name)) + else: + raise KeyError(name) FLAGS = FlagValues() gflags.FLAGS = FLAGS @@ -218,8 +233,11 @@ DEFINE_string('vpn_key_suffix', DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger') +DEFINE_string('state_path', os.path.abspath("./"), + "Top-level directory for maintaining nova's state") + DEFINE_string('sql_connection', - 'sqlite:///%s/nova.sqlite' % os.path.abspath("./"), + 'sqlite:///$state_path/nova.sqlite', 'connection string for sql database') DEFINE_string('compute_manager', 'nova.compute.manager.ComputeManager', diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7b323efa1..f504b3d29 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -38,7 +38,7 @@ flags.DEFINE_string('dhcpbridge_flagfile', '/etc/nova/nova-dhcpbridge.conf', 'location of flagfile for dhcpbridge') -flags.DEFINE_string('networks_path', utils.abspath('../networks'), +flags.DEFINE_string('networks_path', '$state_path/networks', 'Location to keep network config files') flags.DEFINE_string('public_interface', 'vlan1', 'Interface for public IP addresses') diff --git a/nova/objectstore/bucket.py b/nova/objectstore/bucket.py index 0ba4934d1..fce3ec27b 100644 --- a/nova/objectstore/bucket.py +++ b/nova/objectstore/bucket.py @@ -33,7 +33,7 @@ from nova.objectstore import stored FLAGS = flags.FLAGS -flags.DEFINE_string('buckets_path', utils.abspath('../buckets'), +flags.DEFINE_string('buckets_path', '$state_path/buckets', 'path to s3 buckets') diff --git a/nova/objectstore/image.py b/nova/objectstore/image.py index b7b2ec6ab..51aef7343 100644 --- a/nova/objectstore/image.py +++ b/nova/objectstore/image.py @@ -39,8 +39,8 @@ from nova.objectstore import bucket FLAGS = flags.FLAGS -flags.DEFINE_string('images_path', utils.abspath('../images'), - 'path to decrypted images') +flags.DEFINE_string('images_path', '$state_path/images', + 'path to decrypted images') class Image(object): -- cgit From 659058bef7913254eca63e7f67a5d74ffe146e57 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 18 Nov 2010 00:11:45 +0000 Subject: fixes flatdhcp, updates nova.sh, allows for empty bridge device --- contrib/nova.sh | 28 ++++++++++++++++++++-------- nova/network/linux_net.py | 7 ++++--- nova/network/manager.py | 24 +++++++++++++++--------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/contrib/nova.sh b/contrib/nova.sh index 9bc36d6fb..abb8c7de0 100755 --- a/contrib/nova.sh +++ b/contrib/nova.sh @@ -17,11 +17,16 @@ if [ ! -n "$HOST_IP" ]; then # you should explicitly set HOST_IP in your environment HOST_IP=`ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` fi -TEST=0 -USE_MYSQL=0 -MYSQL_PASS=nova -USE_LDAP=0 -LIBVIRT_TYPE=qemu + +USE_MYSQL=${USE_MYSQL:-0} +MYSQL_PASS=${MYSQL_PASS:-nova} +TEST=${TEST:-0} +USE_LDAP=${USE_LDAP:-0} +LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu} +NET_MAN=${NET_MAN:-VlanManager} +# NOTE(vish): If you are using FlatDHCP make sure that this is not your +# public interface. You can comment it out for local usage +BRIDGE_DEV=eth0 if [ "$USE_MYSQL" == 1 ]; then SQL_CONN=mysql://root:$MYSQL_PASS@localhost/nova @@ -41,6 +46,7 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF --nodaemon --dhcpbridge_flagfile=/etc/nova/nova-manage.conf --FAKE_subdomain=ec2 +--network_manager=nova.network.manager.$NET_MAN --cc_host=$HOST_IP --routing_source_ip=$HOST_IP --sql_connection=$SQL_CONN @@ -48,6 +54,10 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF --libvirt_type=$LIBVIRT_TYPE NOVA_CONF_EOF +if [ -n "$BRIDGE_DEV" ]; then + echo "--bridge_dev=$BRIDGE_DEV" >>/etc/nova/nova-manage.conf +fi + if [ "$CMD" == "branch" ]; then sudo apt-get install -y bzr rm -rf $NOVA_DIR @@ -65,6 +75,8 @@ if [ "$CMD" == "install" ]; then sudo apt-get install -y dnsmasq open-iscsi kpartx kvm gawk iptables ebtables sudo apt-get install -y user-mode-linux kvm libvirt-bin sudo apt-get install -y screen iscsitarget euca2ools vlan curl rabbitmq-server + echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget + sudo /etc/init.d/iscsitarget restart sudo modprobe kvm sudo /etc/init.d/libvirt-bin restart sudo apt-get install -y python-twisted python-sqlalchemy python-mox python-greenlet python-carrot @@ -123,8 +135,8 @@ if [ "$CMD" == "run" ]; then $NOVA_DIR/bin/nova-manage project create admin admin # export environment variables for project 'admin' and user 'admin' $NOVA_DIR/bin/nova-manage project environment admin admin $NOVA_DIR/novarc - # create 3 small networks - $NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 3 16 + # create a small network + $NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 1 32 # nova api crashes if we start it with a regular screen command, # so send the start command by forcing text into the window. @@ -135,7 +147,7 @@ if [ "$CMD" == "run" ]; then screen_it scheduler "$NOVA_DIR/bin/nova-scheduler --flagfile=/etc/nova/nova-manage.conf" screen_it volume "$NOVA_DIR/bin/nova-volume --flagfile=/etc/nova/nova-manage.conf" screen_it test ". $NOVA_DIR/novarc" - screen -x + screen -S nova -x fi if [ "$CMD" == "run" ] || [ "$CMD" == "terminate" ]; then diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7b323efa1..68037ed9a 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -42,7 +42,7 @@ flags.DEFINE_string('networks_path', utils.abspath('../networks'), 'Location to keep network config files') flags.DEFINE_string('public_interface', 'vlan1', 'Interface for public IP addresses') -flags.DEFINE_string('bridge_dev', 'eth0', +flags.DEFINE_string('bridge_dev', None, 'network device for bridges') flags.DEFINE_string('dhcpbridge', _bin_file('nova-dhcpbridge'), 'location of nova-dhcpbridge') @@ -142,12 +142,13 @@ def ensure_vlan(vlan_num): def ensure_bridge(bridge, interface, net_attrs=None): """Create a bridge unless it already exists""" if not _device_exists(bridge): - logging.debug("Starting Bridge inteface for %s", interface) + logging.debug("Starting Bridge interface for %s", interface) _execute("sudo brctl addbr %s" % bridge) _execute("sudo brctl setfd %s 0" % bridge) # _execute("sudo brctl setageing %s 10" % bridge) _execute("sudo brctl stp %s off" % bridge) - _execute("sudo brctl addif %s %s" % (bridge, interface)) + if interface: + _execute("sudo brctl addif %s %s" % (bridge, interface)) if net_attrs: _execute("sudo ifconfig %s %s broadcast %s netmask %s up" % \ (bridge, diff --git a/nova/network/manager.py b/nova/network/manager.py index b033bb0a4..96f8cf50b 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -63,7 +63,7 @@ flags.DEFINE_string('flat_network_bridge', 'br100', 'Bridge for simple network instances') flags.DEFINE_string('flat_network_dns', '8.8.4.4', 'Dns for simple network') -flags.DEFINE_string('flat_network_dhcp_start', '192.168.0.2', +flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2', 'Dhcp start for FlatDhcp') flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') flags.DEFINE_integer('num_networks', 1000, 'Number of networks to support') @@ -285,6 +285,7 @@ class FlatManager(NetworkManager): cidr = "%s/%s" % (fixed_net[start], significant_bits) project_net = IPy.IP(cidr) net = {} + net['bridge'] = FLAGS.flat_network_bridge net['cidr'] = cidr net['netmask'] = str(project_net.netmask()) net['gateway'] = str(project_net[1]) @@ -307,17 +308,23 @@ class FlatManager(NetworkManager): """Called when this host becomes the host for a network.""" net = {} net['injected'] = True - net['bridge'] = FLAGS.flat_network_bridge net['dns'] = FLAGS.flat_network_dns self.db.network_update(context, network_id, net) -class FlatDHCPManager(NetworkManager): +class FlatDHCPManager(FlatManager): """Flat networking with dhcp.""" + def setup_compute_network(self, context, instance_id): + """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.bridge_dev, + network_ref) + def setup_fixed_ip(self, context, address): """Setup dhcp for this network.""" - network_ref = db.fixed_ip_get_by_address(context, address) + network_ref = db.fixed_ip_get_network(context, address) self.driver.update_dhcp(context, network_ref['id']) def deallocate_fixed_ip(self, context, address, *args, **kwargs): @@ -326,11 +333,10 @@ class FlatDHCPManager(NetworkManager): def _on_set_network_host(self, context, network_id): """Called when this host becomes the host for a project.""" - super(FlatDHCPManager, self)._on_set_network_host(context, network_id) - network_ref = self.db.network_get(context, network_id) - self.db.network_update(context, - network_id, - {'dhcp_start': FLAGS.flat_network_dhcp_start}) + net = {} + net['dhcp_start'] = FLAGS.flat_network_dhcp_start + self.db.network_update(context, network_id, net) + network_ref = db.network_get(context, network_id) self.driver.ensure_bridge(network_ref['bridge'], FLAGS.bridge_dev, network_ref) -- cgit From 0b70b44c11830549938c5153b4322b960c53963d Mon Sep 17 00:00:00 2001 From: Anne Gentle Date: Mon, 22 Nov 2010 16:43:17 -0600 Subject: Incorporating more networking info --- doc/source/adminguide/index.rst | 6 +++--- doc/source/adminguide/managing.networks.rst | 15 --------------- doc/source/adminguide/network.vlan.rst | 8 ++++---- doc/source/nova.concepts.rst | 21 +++++++++++++++++---- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/doc/source/adminguide/index.rst b/doc/source/adminguide/index.rst index 51228b319..736a154b2 100644 --- a/doc/source/adminguide/index.rst +++ b/doc/source/adminguide/index.rst @@ -38,14 +38,14 @@ There are two main tools that a system administrator will find useful to manage nova.manage euca2ools -nova-manage may only be run by users with admin priviledges. euca2ools can be used by all users, though specific commands may be restricted by Role Based Access Control. You can read more about creating and managing users in :doc:`managing.users` +The nova-manage command may only be run by users with admin priviledges. Commands for euca2ools can be used by all users, though specific commands may be restricted by Role Based Access Control. You can read more about creating and managing users in :doc:`managing.users` User and Resource Management ---------------------------- -nova-manage and euca2ools provide the basic interface to perform a broad range of administration functions. In this section, you can read more about how to accomplish specific administration tasks. +The nova-manage and euca2ools commands provide the basic interface to perform a broad range of administration functions. In this section, you can read more about how to accomplish specific administration tasks. -For background on the core objects refenced in this section, see :doc:`../object.model` +For background on the core objects referenced in this section, see :doc:`../object.model` .. toctree:: :maxdepth: 1 diff --git a/doc/source/adminguide/managing.networks.rst b/doc/source/adminguide/managing.networks.rst index c8df471e8..b8563637e 100644 --- a/doc/source/adminguide/managing.networks.rst +++ b/doc/source/adminguide/managing.networks.rst @@ -20,21 +20,6 @@ Networking Overview =================== In Nova, users organize their cloud resources in projects. A Nova project consists of a number of VM instances created by a user. For each VM instance, Nova assigns to it a private IP address. (Currently, Nova only supports Linux bridge networking that allows the virtual interfaces to connect to the outside network through the physical interface. Other virtual network technologies, such as Open vSwitch, could be supported in the future.) The Network Controller provides virtual networks to enable compute servers to interact with each other and with the public network. -.. - (perhaps some of this should be moved elsewhere) - Introduction - ------------ - - Nova consists of seven main components, with the Cloud Controller component representing the global state and interacting with all other components. API Server acts as the Web services front end for the cloud controller. Compute Controller provides compute server resources, and the Object Store component provides storage services. Auth Manager provides authentication and authorization services. Volume Controller provides fast and permanent block-level storage for the comput servers. Network Controller provides virtual networks to enable compute servers to interact with each other and with the public network. Scheduler selects the most suitable compute controller to host an instance. - - .. todo:: Insert Figure 1 image from "An OpenStack Network Overview" contributed by Citrix - - Nova is built on a shared-nothing, messaging-based architecture. All of the major components, that is Compute Controller, Volume Controller, Network Controller, and Object Store can be run on multiple servers. Cloud Controller communicates with Object Store via HTTP (Hyper Text Transfer Protocol), but it communicates with Scheduler, Network Controller, and Volume Controller via AMQP (Advanced Message Queue Protocol). To avoid blocking each component while waiting for a response, Nova uses asynchronous calls, with a call-back that gets triggered when a response is received. - - To achieve the shared-nothing property with multiple copies of the same component, Nova keeps all the cloud system state in a distributed data store. Updates to system state are written into this store, using atomic transactions when required. Requests for system state are read out of this store. In limited cases, the read results are cached within controllers for short periods of time (for example, the current list of system users.) - - .. note:: The database schema is available on the `OpenStack Wiki _`. - Nova Network Strategies ----------------------- diff --git a/doc/source/adminguide/network.vlan.rst b/doc/source/adminguide/network.vlan.rst index 5bbc54bed..c6c4e7f91 100644 --- a/doc/source/adminguide/network.vlan.rst +++ b/doc/source/adminguide/network.vlan.rst @@ -50,7 +50,7 @@ The following diagram illustrates how the communication that occurs between the Goals ----- -* each project is in a protected network segment +For our implementation of Nova, our goal is that each project is in a protected network segment. Here are the specifications we keep in mind for meeting this goal. * RFC-1918 IP space * public IP via NAT @@ -59,19 +59,19 @@ Goals * limited (project-admin controllable) access to other project segments * all connectivity to instance and cloud API is via VPN into the project segment -* common DMZ segment for support services (only visible from project segment) +We also keep as a goal a common DMZ segment for support services, meaning these items are only visible from project segment: * metadata * dashboard - Limitations ----------- +We kept in mind some of these limitations: + * Projects / cluster limited to available VLANs in switching infrastructure * Requires VPN for access to project segment - Implementation -------------- Currently Nova segregates project VLANs using 802.1q VLAN tagging in the diff --git a/doc/source/nova.concepts.rst b/doc/source/nova.concepts.rst index ddf0f1b82..d47438de7 100644 --- a/doc/source/nova.concepts.rst +++ b/doc/source/nova.concepts.rst @@ -23,13 +23,13 @@ Nova Concepts and Introduction Introduction ------------ -Nova is the software that controls your Infrastructure as as Service (IaaS) +Nova, also known as OpenStack Compute, is the software that controls your Infrastructure as as Service (IaaS) cloud computing platform. It is similar in scope to Amazon EC2 and Rackspace -CloudServers. Nova does not include any virtualization software, rather it +Cloud Servers. Nova does not include any virtualization software, rather it defines drivers that interact with underlying virtualization mechanisms that run on your host operating system, and exposes functionality over a web API. -This document does not attempt to explain fundamental concepts of cloud +This site does not attempt to explain fundamental concepts of cloud computing, IaaS, virtualization, or other related technologies. Instead, it focuses on describing how Nova's implementation of those concepts is achieved. @@ -64,6 +64,19 @@ Concept: Instances An 'instance' is a word for a virtual machine that runs inside the cloud. +Concept: System Architecture +---------------------------- + +Nova consists of seven main components, with the Cloud Controller component representing the global state and interacting with all other components. API Server acts as the Web services front end for the cloud controller. Compute Controller provides compute server resources, and the Object Store component provides storage services. Auth Manager provides authentication and authorization services. Volume Controller provides fast and permanent block-level storage for the comput servers. Network Controller provides virtual networks to enable compute servers to interact with each other and with the public network. Scheduler selects the most suitable compute controller to host an instance. + + .. image:: images/Novadiagram.png + +Nova is built on a shared-nothing, messaging-based architecture. All of the major components, that is Compute Controller, Volume Controller, Network Controller, and Object Store can be run on multiple servers. Cloud Controller communicates with Object Store via HTTP (Hyper Text Transfer Protocol), but it communicates with Scheduler, Network Controller, and Volume Controller via AMQP (Advanced Message Queue Protocol). To avoid blocking each component while waiting for a response, Nova uses asynchronous calls, with a call-back that gets triggered when a response is received. + +To achieve the shared-nothing property with multiple copies of the same component, Nova keeps all the cloud system state in a distributed data store. Updates to system state are written into this store, using atomic transactions when required. Requests for system state are read out of this store. In limited cases, the read results are cached within controllers for short periods of time (for example, the current list of system users.) + + .. note:: The database schema is available on the `OpenStack Wiki _`. + Concept: Storage ---------------- @@ -150,7 +163,7 @@ See doc:`nova.manage` in the Administration Guide for more details. Concept: Flags -------------- -python-gflags +Nova uses python-gflags for a distributed command line system, and the flags can either be set when running a command at the command line or within flag files. When you install Nova packages, each nova service gets its own flag file. For example, nova-network.conf is used for configuring the nova-network service, and so forth. Concept: Plugins -- cgit From a19d0e294efac1fb7e8e3e45a286f6032172da23 Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Mon, 22 Nov 2010 17:59:49 -0500 Subject: Rename cloudServersFault (rackspace branding) to computeFault. Fixes bug lp680285. --- nova/api/openstack/faults.py | 2 +- nova/tests/api/openstack/test_api.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py index e69e51439..224a7ef0b 100644 --- a/nova/api/openstack/faults.py +++ b/nova/api/openstack/faults.py @@ -47,7 +47,7 @@ class Fault(webob.exc.HTTPException): """Generate a WSGI response based on the exception passed to ctor.""" # Replace the body with fault details. code = self.wrapped_exc.status_int - fault_name = self._fault_names.get(code, "cloudServersFault") + fault_name = self._fault_names.get(code, "computeFault") fault_data = { fault_name: { 'code': code, diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py index dd83991b9..d8b202e21 100644 --- a/nova/tests/api/openstack/test_api.py +++ b/nova/tests/api/openstack/test_api.py @@ -50,12 +50,12 @@ class APITest(unittest.TestCase): api.application = succeed resp = Request.blank('/').get_response(api) - self.assertFalse('cloudServersFault' in resp.body, resp.body) + self.assertFalse('computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 200, resp.body) api.application = raise_webob_exc resp = Request.blank('/').get_response(api) - self.assertFalse('cloudServersFault' in resp.body, resp.body) + self.assertFalse('computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 404, resp.body) api.application = raise_api_fault @@ -65,10 +65,10 @@ class APITest(unittest.TestCase): api.application = fail resp = Request.blank('/').get_response(api) - self.assertTrue('{"cloudServersFault' in resp.body, resp.body) + self.assertTrue('{"computeFault' in resp.body, resp.body) self.assertEqual(resp.status_int, 500, resp.body) api.application = fail resp = Request.blank('/.xml').get_response(api) - self.assertTrue(' Date: Mon, 22 Nov 2010 17:03:54 -0600 Subject: Incorporating security groups info --- doc/source/devref/cloudpipe.rst | 2 +- doc/source/nova.concepts.rst | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/source/devref/cloudpipe.rst b/doc/source/devref/cloudpipe.rst index 31bd85e81..fb104c160 100644 --- a/doc/source/devref/cloudpipe.rst +++ b/doc/source/devref/cloudpipe.rst @@ -21,7 +21,7 @@ Cloudpipe -- Per Project Vpns ============================= -Cloudpipe is a method for connecting end users to their project insnances in vlan mode. +Cloudpipe is a method for connecting end users to their project instances in vlan mode. Overview diff --git a/doc/source/nova.concepts.rst b/doc/source/nova.concepts.rst index d47438de7..18368546b 100644 --- a/doc/source/nova.concepts.rst +++ b/doc/source/nova.concepts.rst @@ -117,9 +117,9 @@ Concept: API Concept: Networking ------------------- -Nova has a concept of Fixed Ips and Floating ips. Fixed ips are assigned to an instance on creation and stay the same until the instance is explicitly terminated. Floating ips are ip addresses that can be dynamically associated with an instance. This address can be disassociated and associated with another instance at any time. +Nova has a concept of Fixed IPs and Floating IPs. Fixed IPs are assigned to an instance on creation and stay the same until the instance is explicitly terminated. Floating ips are ip addresses that can be dynamically associated with an instance. This address can be disassociated and associated with another instance at any time. -There are multiple strategies available for implementing fixed ips: +There are multiple strategies available for implementing fixed IPs: Flat Mode ~~~~~~~~~ @@ -129,7 +129,7 @@ The simplest networking mode. Each instance receives a fixed ip from the pool. Flat DHCP Mode ~~~~~~~~~~~~~~ -This is similar to the flat mode, in that all instances are attached to the same bridge. In this mode nova does a bit more configuration, it will attempt to bridge into an ethernet device (eth0 by default). It will also run dnsmasq as a dhcpserver listening on this bridge. Instances receive their fixed ips by doing a dhcpdiscover. +This is similar to the flat mode, in that all instances are attached to the same bridge. In this mode nova does a bit more configuration, it will attempt to bridge into an ethernet device (eth0 by default). It will also run dnsmasq as a dhcpserver listening on this bridge. Instances receive their fixed IPs by doing a dhcpdiscover. VLAN DHCP Mode ~~~~~~~~~~~~~~ @@ -200,8 +200,17 @@ Concept: Scheduler Concept: Security Groups ------------------------ -Security groups +In Nova, a security group is a named collection of network access rules, like firewall policies. These access rules specify which incoming network traffic should be delivered to all VM instances in the group, all other incoming traffic being discarded. Users can modify rules for a group at any time. The new rules are automatically enforced for all running instances and instances launched from then on. +When launching VM instances, the project manager specifies which security groups it wants to join. It will become a member of these specified security groups when it is launched. If no groups are specified, the instances is assigned to the default group, which by default allows all network traffic from other members of this group and discards traffic from other IP addresses and groups. If this does not meet a user's needs, the user can modify the rule settings of the default group. + +A security group can be thought of as a security profile or a security role - it promotes the good practice of managing firewalls by role, not by machine. For example, a user could stipulate that servers with the "webapp" role must be able to connect to servers with the "mysql" role on port 3306. Going further with the security profile analogy, an instance can be launched with membership of multiple security groups - similar to a server with multiple roles. Because all rules in security groups are ACCEPT rules, it's trivial to combine them. + +Each rule in a security group must specify the source of packets to be allowed, which can either be a subnet anywhere on the Internet (in CIDR notation, with 0.0.0./0 representing the entire Internet) or another security group. In the latter case, the source security group can be any user's group. This makes it easy to grant selective access to one user's instances from instances run by the user's friends, partners, and vendors. + +The creation of rules with other security groups specified as sources helps users deal with dynamic IP addressing. Without this feature, the user would have had to adjust the security groups each time a new instance is launched. This practice would become cumbersome if an application running in Nova is very dynamic and elastic, for example scales up or down frequently. + +Security groups for a VM are passed at launch time by the cloud controller to the compute node, and applied at the compute node when a VM is started. Concept: Certificate Authority ------------------------------ -- cgit From 693624831066af08dcf488d1528b017048fbde71 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Nov 2010 17:56:43 +0000 Subject: changed bridge_dev to vlan_interface --- 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 68037ed9a..d39ed9f86 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -42,8 +42,8 @@ flags.DEFINE_string('networks_path', utils.abspath('../networks'), 'Location to keep network config files') flags.DEFINE_string('public_interface', 'vlan1', 'Interface for public IP addresses') -flags.DEFINE_string('bridge_dev', None, - 'network device for bridges') +flags.DEFINE_string('vlan_interface', 'eth0', + 'network device for vlans') flags.DEFINE_string('dhcpbridge', _bin_file('nova-dhcpbridge'), 'location of nova-dhcpbridge') flags.DEFINE_string('routing_source_ip', '127.0.0.1', @@ -134,7 +134,7 @@ def ensure_vlan(vlan_num): if not _device_exists(interface): logging.debug("Starting VLAN inteface %s", interface) _execute("sudo vconfig set_name_type VLAN_PLUS_VID_NO_PAD") - _execute("sudo vconfig add %s %s" % (FLAGS.bridge_dev, vlan_num)) + _execute("sudo vconfig add %s %s" % (FLAGS.vlan_interface, vlan_num)) _execute("sudo ifconfig %s up" % interface) return interface -- cgit From 6811f824f7c1edd1b3882621d80fba54a2bf019d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Nov 2010 17:57:12 +0000 Subject: added flat_interface for flat_dhcp binding --- 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 96f8cf50b..8f13a8230 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -61,6 +61,8 @@ from nova import utils FLAGS = flags.FLAGS flags.DEFINE_string('flat_network_bridge', 'br100', 'Bridge for simple network instances') +flags.DEFINE_string('flat_interface', None, + 'flat_dhcp will bridge into this interface if set') flags.DEFINE_string('flat_network_dns', '8.8.4.4', 'Dns for simple network') flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2', @@ -319,7 +321,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.bridge_dev, + FLAGS.flat_interface, network_ref) def setup_fixed_ip(self, context, address): @@ -338,7 +340,7 @@ class FlatDHCPManager(FlatManager): self.db.network_update(context, network_id, net) network_ref = db.network_get(context, network_id) self.driver.ensure_bridge(network_ref['bridge'], - FLAGS.bridge_dev, + FLAGS.flat_interface, network_ref) -- cgit From 015b7e5848c010ab86f067fb5dff462c2f34f4f9 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Nov 2010 17:57:25 +0000 Subject: updated nova.sh --- contrib/nova.sh | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/contrib/nova.sh b/contrib/nova.sh index abb8c7de0..8cbd5f605 100755 --- a/contrib/nova.sh +++ b/contrib/nova.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash DIR=`pwd` CMD=$1 -SOURCE_BRANCH=lp:nova +SOURCE_BRANCH=lp:~anso/nova/deploy if [ -n "$2" ]; then SOURCE_BRANCH=$2 fi -DIRNAME=nova +DIRNAME=deploy NOVA_DIR=$DIR/$DIRNAME if [ -n "$3" ]; then NOVA_DIR=$DIR/$3 @@ -17,11 +17,10 @@ if [ ! -n "$HOST_IP" ]; then # you should explicitly set HOST_IP in your environment HOST_IP=`ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` fi - USE_MYSQL=${USE_MYSQL:-0} MYSQL_PASS=${MYSQL_PASS:-nova} TEST=${TEST:-0} -USE_LDAP=${USE_LDAP:-0} +USE_LDAP=${USE_LDAP:-1} LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu} NET_MAN=${NET_MAN:-VlanManager} # NOTE(vish): If you are using FlatDHCP make sure that this is not your @@ -48,14 +47,15 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF --FAKE_subdomain=ec2 --network_manager=nova.network.manager.$NET_MAN --cc_host=$HOST_IP +--cc_dmz=$HOST_IP --routing_source_ip=$HOST_IP --sql_connection=$SQL_CONN --auth_driver=nova.auth.$AUTH --libvirt_type=$LIBVIRT_TYPE NOVA_CONF_EOF -if [ -n "$BRIDGE_DEV" ]; then - echo "--bridge_dev=$BRIDGE_DEV" >>/etc/nova/nova-manage.conf +if [ -n "$FLAT_INTERFACE" ]; then + echo "--flat_interface=$FLAT_INTERFACE" >>/etc/nova/nova-manage.conf fi if [ "$CMD" == "branch" ]; then @@ -72,9 +72,10 @@ if [ "$CMD" == "install" ]; then sudo apt-get install -y python-software-properties sudo add-apt-repository ppa:nova-core/ppa sudo apt-get update - sudo apt-get install -y dnsmasq open-iscsi kpartx kvm gawk iptables ebtables + sudo apt-get install -y dnsmasq kpartx kvm gawk iptables ebtables sudo apt-get install -y user-mode-linux kvm libvirt-bin - sudo apt-get install -y screen iscsitarget euca2ools vlan curl rabbitmq-server + sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server + sudo apt-get install -y lvm2 iscsitarget open-iscsi echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget sudo /etc/init.d/iscsitarget restart sudo modprobe kvm @@ -119,6 +120,9 @@ if [ "$CMD" == "run" ]; then rm -rf $NOVA_DIR/networks mkdir -p $NOVA_DIR/networks $NOVA_DIR/tools/clean-vlans + sleep 3 + ifdown eth0 + ifup eth0 if [ ! -d "$NOVA_DIR/images" ]; then ln -s $DIR/images $NOVA_DIR/images fi @@ -147,6 +151,11 @@ if [ "$CMD" == "run" ]; then screen_it scheduler "$NOVA_DIR/bin/nova-scheduler --flagfile=/etc/nova/nova-manage.conf" screen_it volume "$NOVA_DIR/bin/nova-volume --flagfile=/etc/nova/nova-manage.conf" screen_it test ". $NOVA_DIR/novarc" + + sleep 3 + + $NOVA_DIR/bin/nova-manage service enable `hostname` nova-compute + $NOVA_DIR/bin/nova-manage service enable `hostname` nova-volume screen -S nova -x fi @@ -154,12 +163,13 @@ if [ "$CMD" == "run" ] || [ "$CMD" == "terminate" ]; then # shutdown instances . $NOVA_DIR/novarc; euca-describe-instances | grep i- | cut -f2 | xargs euca-terminate-instances sleep 2 + # delete volumes + . $NOVA_DIR/novarc; euca-describe-volumes | grep vol- | cut -f2 | xargs -n1 euca-delete-volume fi if [ "$CMD" == "run" ] || [ "$CMD" == "clean" ]; then screen -S nova -X quit rm *.pid* - $NOVA_DIR/tools/setup_iptables.sh clear fi if [ "$CMD" == "scrub" ]; then @@ -169,5 +179,4 @@ if [ "$CMD" == "scrub" ]; then else virsh list | grep i- | awk '{print \$1}' | xargs -n1 virsh destroy fi - vblade-persist ls | grep vol- | awk '{print \$1\" \"\$2}' | xargs -n2 vblade-persist destroy fi -- cgit From 84521218b84d2eed307364c9efc9f6f2ee212aac Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Nov 2010 23:18:02 +0000 Subject: docstrings, more flags, breakout of metadata forwarding --- nova/network/linux_net.py | 10 +++---- nova/network/manager.py | 67 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index d39ed9f86..b30ddb667 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -53,15 +53,15 @@ flags.DEFINE_bool('use_nova_chains', False, DEFAULT_PORTS = [("tcp", 80), ("tcp", 22), ("udp", 1194), ("tcp", 443)] - -def init_host(): - """Basic networking setup goes here""" - # NOTE(devcamcar): Cloud public DNAT entries, CloudPipe port - # forwarding entries and a default DNAT entry. +def metadata_forward(): + """Create forwarding rule for metadata""" _confirm_rule("PREROUTING", "-t nat -s 0.0.0.0/0 " "-d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j DNAT " "--to-destination %s:%s" % (FLAGS.cc_host, FLAGS.cc_port)) + +def init_host(): + """Basic networking setup goes here""" # NOTE(devcamcar): Cloud public SNAT entries and the default # SNAT rule for outbound traffic. _confirm_rule("POSTROUTING", "-t nat -s %s " diff --git a/nova/network/manager.py b/nova/network/manager.py index 8f13a8230..f9489d2ad 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -27,6 +27,7 @@ topologies. All of the network commands are issued to a subclass of :network_driver: Driver to use for network creation :flat_network_bridge: Bridge device for simple network instances +:flat_interface: FlatDhcp will bridge into this interface if set :flat_network_dns: Dns for simple network :flat_network_dhcp_start: Dhcp start for FlatDhcp :vlan_start: First VLAN for private networks @@ -61,10 +62,12 @@ from nova import utils FLAGS = flags.FLAGS flags.DEFINE_string('flat_network_bridge', 'br100', 'Bridge for simple network instances') -flags.DEFINE_string('flat_interface', None, - 'flat_dhcp will bridge into this interface if set') flags.DEFINE_string('flat_network_dns', '8.8.4.4', 'Dns for simple network') +flags.DEFINE_bool('flat_injected', True, + 'Whether to attempt to inject network setup into guest') +flags.DEFINE_string('flat_interface', None, + 'FlatDhcp will bridge into this interface if set') flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2', 'Dhcp start for FlatDhcp') flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks') @@ -177,9 +180,11 @@ class NetworkManager(manager.Manager): if instance_ref['mac_address'] != mac: raise exception.Error("IP %s leased to bad mac %s vs %s" % (address, instance_ref['mac_address'], mac)) + now = datetime.datetime.utcnow() self.db.fixed_ip_update(context, fixed_ip_ref['address'], - {'leased': True}) + {'leased': True, + 'updated_at': now}) if not fixed_ip_ref['allocated']: logging.warn("IP %s leased that was already deallocated", address) @@ -248,7 +253,31 @@ class NetworkManager(manager.Manager): class FlatManager(NetworkManager): - """Basic network where no vlans are used.""" + """Basic network where no vlans are used. + + FlatManager does not do any bridge or vlan creation. The user is + responsible for setting up whatever bridge is specified in + flat_network_bridge (br100 by default). This bridge needs to be created + on all compute hosts. + + The idea is to create a single network for the host with a command like: + nova-manage network create 192.168.0.0/24 256 1. Creating multiple + networks for for one manager is currently not supported, but could be + added by modifying allocate_fixed_ip and get_network to get the a network + with new logic instead of network_get_by_bridge. Arbitrary lists of + addresses in a single network can be accomplished with manual db editing. + + If flat_injected is True, the compute host will attempt to inject network + config into the guest. It attempts to modify /etc/network/interfaces and + currently only works on debian based systems. To support a wider range of + OSes, some other method may need to be devised to let the guest know which + ip it should be using so that it can configure itself. Perhaps an attached + disk or serial device with configuration info. + + Metadata forwarding must be handled by the gateway, and since nova does + not do any setup in this mode, it must be done manually. Requests to + 169.254.169.254 port 80 will need to be forwarded to the api server. + """ def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): """Gets a fixed ip from the pool.""" @@ -309,13 +338,25 @@ class FlatManager(NetworkManager): def _on_set_network_host(self, context, network_id): """Called when this host becomes the host for a network.""" net = {} - net['injected'] = True + net['injected'] = FLAGS.flat_injected net['dns'] = FLAGS.flat_network_dns self.db.network_update(context, network_id, net) class FlatDHCPManager(FlatManager): - """Flat networking with dhcp.""" + """Flat networking with dhcp. + + FlatDHCPManager will start up one dhcp server to give out addresses. + It never injects network settings into the guest. Otherwise it behaves + like FlatDHCPManager. + """ + + def init_host(self): + """Do any initialization that needs to be run if this is a + standalone service. + """ + super(FlatDHCPManager, self).init_host() + self.driver.metadata_forward() def setup_compute_network(self, context, instance_id): """Sets up matching network for compute hosts.""" @@ -345,7 +386,18 @@ class FlatDHCPManager(FlatManager): class VlanManager(NetworkManager): - """Vlan network with dhcp.""" + """Vlan network with dhcp. + + VlanManager is the most complicated. It will create a host-managed + vlan for each project. Each project gets its own subnet. The networks + and associated subnets are created with nova-manage using a command like: + nova-manage network create 10.0.0.0/8 16 3. This will create 3 networks + of 16 addresses from the beginning of the 10.0.0.0 range. + + A dhcp server is run for each subnet, so each project will have its own. + For this mode to be useful, each project will need a vpn to access the + instances in its subnet. + """ @defer.inlineCallbacks def periodic_tasks(self, context=None): @@ -365,6 +417,7 @@ class VlanManager(NetworkManager): standalone service. """ super(VlanManager, self).init_host() + self.driver.metadata_forward() self.driver.init_host() def allocate_fixed_ip(self, context, instance_id, *args, **kwargs): -- cgit From 521dd52e49feeae04108f3e21480f42456b4e4c7 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Nov 2010 23:56:26 +0000 Subject: fix typos in docstring --- nova/network/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/network/manager.py b/nova/network/manager.py index f9489d2ad..a7298b47f 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -261,7 +261,7 @@ class FlatManager(NetworkManager): on all compute hosts. The idea is to create a single network for the host with a command like: - nova-manage network create 192.168.0.0/24 256 1. Creating multiple + nova-manage network create 192.168.0.0/24 1 256. Creating multiple networks for for one manager is currently not supported, but could be added by modifying allocate_fixed_ip and get_network to get the a network with new logic instead of network_get_by_bridge. Arbitrary lists of @@ -391,7 +391,7 @@ class VlanManager(NetworkManager): VlanManager is the most complicated. It will create a host-managed vlan for each project. Each project gets its own subnet. The networks and associated subnets are created with nova-manage using a command like: - nova-manage network create 10.0.0.0/8 16 3. This will create 3 networks + nova-manage network create 10.0.0.0/8 3 16. This will create 3 networks of 16 addresses from the beginning of the 10.0.0.0 range. A dhcp server is run for each subnet, so each project will have its own. -- cgit From d62d3f7bcf06802662f77f8013c9da99eccec0a7 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 24 Nov 2010 00:16:47 +0000 Subject: pep8 --- nova/network/linux_net.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7dbf6b733..391abfb76 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -53,6 +53,7 @@ flags.DEFINE_bool('use_nova_chains', False, DEFAULT_PORTS = [("tcp", 80), ("tcp", 22), ("udp", 1194), ("tcp", 443)] + def metadata_forward(): """Create forwarding rule for metadata""" _confirm_rule("PREROUTING", "-t nat -s 0.0.0.0/0 " -- cgit From 309c8b8ff8732e8d80c445381aee7e1f9852def6 Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Wed, 24 Nov 2010 22:10:21 +0000 Subject: Adding support for modification only of user accounts. --- nova/auth/ldapdriver.py | 110 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 26 deletions(-) diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index ceade1d65..d1ef37cf0 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -40,6 +40,8 @@ flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com', flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users') flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com', 'OU for Users') +flags.DEFINE_boolean('ldap_user_modify_only', False, + 'Modify attributes for users instead of creating/deleting') flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com', 'OU for Projects') flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com', @@ -89,8 +91,7 @@ class LdapDriver(object): def get_user(self, uid): """Retrieve user by id""" - attr = self.__find_object(self.__uid_to_dn(uid), - '(objectclass=novaUser)') + attr = self.__get_ldap_user(uid) return self.__to_user(attr) def get_user_from_access_key(self, access): @@ -110,7 +111,12 @@ class LdapDriver(object): """Retrieve list of users""" attrs = self.__find_objects(FLAGS.ldap_user_subtree, '(objectclass=novaUser)') - return [self.__to_user(attr) for attr in attrs] + users = [] + for attr in attrs: + user = self.__to_user(attr) + if user != None: + users.append(user) + return users def get_projects(self, uid=None): """Retrieve list of projects""" @@ -125,21 +131,46 @@ class LdapDriver(object): """Create a user""" if self.__user_exists(name): raise exception.Duplicate("LDAP user %s already exists" % name) - attr = [ - ('objectclass', ['person', - 'organizationalPerson', - 'inetOrgPerson', - 'novaUser']), - ('ou', [FLAGS.ldap_user_unit]), - ('uid', [name]), - ('sn', [name]), - ('cn', [name]), - ('secretKey', [secret_key]), - ('accessKey', [access_key]), - ('isAdmin', [str(is_admin).upper()]), - ] - self.conn.add_s(self.__uid_to_dn(name), attr) - return self.__to_user(dict(attr)) + if FLAGS.ldap_user_modify_only: + if self.__ldap_user_exists(name): + # Retrieve user by name + user = self.__get_ldap_user(name) + if user.has_key('accessKey') and user.has_key('secretKey') and user.has_key('isAdmin'): + raise exception.Duplicate("LDAP user %s already exists" % name) + else: + # Entry could be malformed, test for missing attrs. + # Malformed entries are useless, replace attributes found. + attr = [] + if user.has_key('secretKey'): + attr.append((self.ldap.MOD_REPLACE, 'secretKey', [secret_key])) + else: + attr.append((self.ldap.MOD_ADD, 'secretKey', [secret_key])) + if user.has_key('accessKey'): + attr.append((self.ldap.MOD_REPLACE, 'accessKey', [access_key])) + else: + attr.append((self.ldap.MOD_ADD, 'accessKey', [access_key])) + if user.has_key('isAdmin'): + attr.append((self.ldap.MOD_REPLACE, 'isAdmin', [str(is_admin).upper()])) + else: + attr.append((self.ldap.MOD_ADD, 'isAdmin', [str(is_admin).upper()])) + self.conn.modify_s(self.__uid_to_dn(name), attr) + return self.get_user(name) + else: + attr = [ + ('objectclass', ['person', + 'organizationalPerson', + 'inetOrgPerson', + 'novaUser']), + ('ou', [FLAGS.ldap_user_unit]), + ('uid', [name]), + ('sn', [name]), + ('cn', [name]), + ('secretKey', [secret_key]), + ('accessKey', [access_key]), + ('isAdmin', [str(is_admin).upper()]), + ] + self.conn.add_s(self.__uid_to_dn(name), attr) + return self.__to_user(dict(attr)) def create_project(self, name, manager_uid, description=None, member_uids=None): @@ -256,7 +287,21 @@ class LdapDriver(object): if not self.__user_exists(uid): raise exception.NotFound("User %s doesn't exist" % uid) self.__remove_from_all(uid) - self.conn.delete_s(self.__uid_to_dn(uid)) + if FLAGS.ldap_user_modify_only: + # Delete attributes + attr = [] + # Retrieve user by name + user = self.__get_ldap_user(uid) + if user.has_key('secretKey'): + attr.append((self.ldap.MOD_DELETE, 'secretKey', user['secretKey'])) + if user.has_key('accessKey'): + attr.append((self.ldap.MOD_DELETE, 'accessKey', user['accessKey'])) + if user.has_key('isAdmin'): + attr.append((self.ldap.MOD_DELETE, 'isAdmin', user['isAdmin'])) + self.conn.modify_s(self.__uid_to_dn(uid), attr) + else: + # Delete entry + self.conn.delete_s(self.__uid_to_dn(uid)) def delete_project(self, project_id): """Delete a project""" @@ -265,7 +310,7 @@ class LdapDriver(object): self.__delete_group(project_dn) def modify_user(self, uid, access_key=None, secret_key=None, admin=None): - """Modify an existing project""" + """Modify an existing user""" if not access_key and not secret_key and admin is None: return attr = [] @@ -281,10 +326,20 @@ class LdapDriver(object): """Check if user exists""" return self.get_user(uid) != None + def __ldap_user_exists(self, uid): + """Check if the user exists in ldap""" + return self.__get_ldap_user(uid) != None + def __project_exists(self, project_id): """Check if project exists""" return self.get_project(project_id) != None + def __get_ldap_user(self, uid): + """Retrieve LDAP user entry by id""" + attr = self.__find_object(self.__uid_to_dn(uid), + '(objectclass=novaUser)') + return attr + def __find_object(self, dn, query=None, scope=None): """Find an object by dn and query""" objects = self.__find_objects(dn, query, scope) @@ -449,12 +504,15 @@ class LdapDriver(object): """Convert ldap attributes to User object""" if attr == None: return None - return { - 'id': attr['uid'][0], - 'name': attr['cn'][0], - 'access': attr['accessKey'][0], - 'secret': attr['secretKey'][0], - 'admin': (attr['isAdmin'][0] == 'TRUE')} + if (attr.has_key('accessKey') and attr.has_key('secretKey') and attr.has_key('isAdmin')): + return { + 'id': attr['uid'][0], + 'name': attr['uid'][0], + 'access': attr['accessKey'][0], + 'secret': attr['secretKey'][0], + 'admin': (attr['isAdmin'][0] == 'TRUE')} + else: + return None def __to_project(self, attr): """Convert ldap attributes to Project object""" -- cgit From d7515bcb1d35e2e558a01c381b1d3a22165daa4b Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Wed, 24 Nov 2010 22:34:52 +0000 Subject: Setting "name" back to "cn", since id and name should be separate --- nova/auth/ldapdriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index d1ef37cf0..95519d000 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -507,7 +507,7 @@ class LdapDriver(object): if (attr.has_key('accessKey') and attr.has_key('secretKey') and attr.has_key('isAdmin')): return { 'id': attr['uid'][0], - 'name': attr['uid'][0], + 'name': attr['cn'][0], 'access': attr['accessKey'][0], 'secret': attr['secretKey'][0], 'admin': (attr['isAdmin'][0] == 'TRUE')} -- cgit From 725a1f638b01985a2ae9a4f0a68f16ef31914a51 Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Fri, 26 Nov 2010 17:01:50 +0000 Subject: This modification should have occured in a different branch. Reverting. --- nova/auth/ldapdriver.py | 110 ++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 84 deletions(-) diff --git a/nova/auth/ldapdriver.py b/nova/auth/ldapdriver.py index 95519d000..ceade1d65 100644 --- a/nova/auth/ldapdriver.py +++ b/nova/auth/ldapdriver.py @@ -40,8 +40,6 @@ flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com', flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users') flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com', 'OU for Users') -flags.DEFINE_boolean('ldap_user_modify_only', False, - 'Modify attributes for users instead of creating/deleting') flags.DEFINE_string('ldap_project_subtree', 'ou=Groups,dc=example,dc=com', 'OU for Projects') flags.DEFINE_string('role_project_subtree', 'ou=Groups,dc=example,dc=com', @@ -91,7 +89,8 @@ class LdapDriver(object): def get_user(self, uid): """Retrieve user by id""" - attr = self.__get_ldap_user(uid) + attr = self.__find_object(self.__uid_to_dn(uid), + '(objectclass=novaUser)') return self.__to_user(attr) def get_user_from_access_key(self, access): @@ -111,12 +110,7 @@ class LdapDriver(object): """Retrieve list of users""" attrs = self.__find_objects(FLAGS.ldap_user_subtree, '(objectclass=novaUser)') - users = [] - for attr in attrs: - user = self.__to_user(attr) - if user != None: - users.append(user) - return users + return [self.__to_user(attr) for attr in attrs] def get_projects(self, uid=None): """Retrieve list of projects""" @@ -131,46 +125,21 @@ class LdapDriver(object): """Create a user""" if self.__user_exists(name): raise exception.Duplicate("LDAP user %s already exists" % name) - if FLAGS.ldap_user_modify_only: - if self.__ldap_user_exists(name): - # Retrieve user by name - user = self.__get_ldap_user(name) - if user.has_key('accessKey') and user.has_key('secretKey') and user.has_key('isAdmin'): - raise exception.Duplicate("LDAP user %s already exists" % name) - else: - # Entry could be malformed, test for missing attrs. - # Malformed entries are useless, replace attributes found. - attr = [] - if user.has_key('secretKey'): - attr.append((self.ldap.MOD_REPLACE, 'secretKey', [secret_key])) - else: - attr.append((self.ldap.MOD_ADD, 'secretKey', [secret_key])) - if user.has_key('accessKey'): - attr.append((self.ldap.MOD_REPLACE, 'accessKey', [access_key])) - else: - attr.append((self.ldap.MOD_ADD, 'accessKey', [access_key])) - if user.has_key('isAdmin'): - attr.append((self.ldap.MOD_REPLACE, 'isAdmin', [str(is_admin).upper()])) - else: - attr.append((self.ldap.MOD_ADD, 'isAdmin', [str(is_admin).upper()])) - self.conn.modify_s(self.__uid_to_dn(name), attr) - return self.get_user(name) - else: - attr = [ - ('objectclass', ['person', - 'organizationalPerson', - 'inetOrgPerson', - 'novaUser']), - ('ou', [FLAGS.ldap_user_unit]), - ('uid', [name]), - ('sn', [name]), - ('cn', [name]), - ('secretKey', [secret_key]), - ('accessKey', [access_key]), - ('isAdmin', [str(is_admin).upper()]), - ] - self.conn.add_s(self.__uid_to_dn(name), attr) - return self.__to_user(dict(attr)) + attr = [ + ('objectclass', ['person', + 'organizationalPerson', + 'inetOrgPerson', + 'novaUser']), + ('ou', [FLAGS.ldap_user_unit]), + ('uid', [name]), + ('sn', [name]), + ('cn', [name]), + ('secretKey', [secret_key]), + ('accessKey', [access_key]), + ('isAdmin', [str(is_admin).upper()]), + ] + self.conn.add_s(self.__uid_to_dn(name), attr) + return self.__to_user(dict(attr)) def create_project(self, name, manager_uid, description=None, member_uids=None): @@ -287,21 +256,7 @@ class LdapDriver(object): if not self.__user_exists(uid): raise exception.NotFound("User %s doesn't exist" % uid) self.__remove_from_all(uid) - if FLAGS.ldap_user_modify_only: - # Delete attributes - attr = [] - # Retrieve user by name - user = self.__get_ldap_user(uid) - if user.has_key('secretKey'): - attr.append((self.ldap.MOD_DELETE, 'secretKey', user['secretKey'])) - if user.has_key('accessKey'): - attr.append((self.ldap.MOD_DELETE, 'accessKey', user['accessKey'])) - if user.has_key('isAdmin'): - attr.append((self.ldap.MOD_DELETE, 'isAdmin', user['isAdmin'])) - self.conn.modify_s(self.__uid_to_dn(uid), attr) - else: - # Delete entry - self.conn.delete_s(self.__uid_to_dn(uid)) + self.conn.delete_s(self.__uid_to_dn(uid)) def delete_project(self, project_id): """Delete a project""" @@ -310,7 +265,7 @@ class LdapDriver(object): self.__delete_group(project_dn) def modify_user(self, uid, access_key=None, secret_key=None, admin=None): - """Modify an existing user""" + """Modify an existing project""" if not access_key and not secret_key and admin is None: return attr = [] @@ -326,20 +281,10 @@ class LdapDriver(object): """Check if user exists""" return self.get_user(uid) != None - def __ldap_user_exists(self, uid): - """Check if the user exists in ldap""" - return self.__get_ldap_user(uid) != None - def __project_exists(self, project_id): """Check if project exists""" return self.get_project(project_id) != None - def __get_ldap_user(self, uid): - """Retrieve LDAP user entry by id""" - attr = self.__find_object(self.__uid_to_dn(uid), - '(objectclass=novaUser)') - return attr - def __find_object(self, dn, query=None, scope=None): """Find an object by dn and query""" objects = self.__find_objects(dn, query, scope) @@ -504,15 +449,12 @@ class LdapDriver(object): """Convert ldap attributes to User object""" if attr == None: return None - if (attr.has_key('accessKey') and attr.has_key('secretKey') and attr.has_key('isAdmin')): - return { - 'id': attr['uid'][0], - 'name': attr['cn'][0], - 'access': attr['accessKey'][0], - 'secret': attr['secretKey'][0], - 'admin': (attr['isAdmin'][0] == 'TRUE')} - else: - return None + return { + 'id': attr['uid'][0], + 'name': attr['cn'][0], + 'access': attr['accessKey'][0], + 'secret': attr['secretKey'][0], + 'admin': (attr['isAdmin'][0] == 'TRUE')} def __to_project(self, attr): """Convert ldap attributes to Project object""" -- cgit From a7fe9d8cbc4bb6b2ca4306c0adff46edcb2fce6f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 29 Nov 2010 14:02:03 +0100 Subject: Add include_package_data=True to setup.py. This makes sure the various templates get installed into the python path when running "python setup.py install". --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index ec0014478..d88bc1e6f 100644 --- a/setup.py +++ b/setup.py @@ -57,6 +57,7 @@ setup(name='nova', cmdclass={ 'sdist': local_sdist, 'build_sphinx' : local_BuildDoc }, packages=find_packages(exclude=['bin', 'smoketests']), + include_package_data=True, scripts=['bin/nova-api', 'bin/nova-compute', 'bin/nova-dhcpbridge', -- cgit From c8f6db354f5e8f55b432854d5259dcf84f0c8ba0 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 29 Nov 2010 15:49:12 +0100 Subject: Make sure templated flags work across calls to ParseNewFlags. ParseNewFlags creates a new FlagValues object, which doesn't have all the previously defined flags, so template lookups fail miserably. Pass the existing FlagValues object too the template mapping object to fix this. --- nova/flags.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index 70a049491..641bda5f9 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -40,11 +40,12 @@ class FlagValues(gflags.FlagValues): """ - def __init__(self): + def __init__(self, extra_context=None): gflags.FlagValues.__init__(self) self.__dict__['__dirty'] = [] self.__dict__['__was_already_parsed'] = False self.__dict__['__stored_argv'] = [] + self.__dict__['__extra_context'] = extra_context def __call__(self, argv): # We're doing some hacky stuff here so that we don't have to copy @@ -114,7 +115,7 @@ class FlagValues(gflags.FlagValues): def ParseNewFlags(self): if '__stored_argv' not in self.__dict__: return - new_flags = FlagValues() + new_flags = FlagValues(self) for k in self.__dict__['__dirty']: new_flags[k] = gflags.FlagValues.__getitem__(self, k) @@ -139,18 +140,25 @@ class FlagValues(gflags.FlagValues): val = gflags.FlagValues.__getattr__(self, name) if type(val) is str: tmpl = Template(val) - return tmpl.substitute(StrWrapper(self)) + context = [self, self.__dict__['__extra_context']] + return tmpl.substitute(StrWrapper(context)) return val + class StrWrapper(object): - def __init__(self, obj): - self.wrapped = obj + """Wrapper around FlagValues objects + + Wraps FlagValues objects for string.Template so that we're + sure to return strings.""" + def __init__(self, context_objs): + self.context_objs = context_objs def __getitem__(self, name): - if hasattr(self.wrapped, name): - return str(getattr(self.wrapped, name)) - else: - raise KeyError(name) + for context in self.context_objs: + val = getattr(context, name, False) + if val: + return str(val) + raise KeyError(name) FLAGS = FlagValues() gflags.FLAGS = FLAGS -- cgit From 28927f0c9688dd7f3c84a1eda4cc646a1aff7896 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 29 Nov 2010 21:05:40 +0100 Subject: Import string instead of importing Template from string. This is how we do things. --- nova/flags.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index 641bda5f9..948729449 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -24,10 +24,9 @@ where they're used. import getopt import os import socket +import string import sys -from string import Template - import gflags @@ -139,7 +138,7 @@ class FlagValues(gflags.FlagValues): self.ParseNewFlags() val = gflags.FlagValues.__getattr__(self, name) if type(val) is str: - tmpl = Template(val) + tmpl = string.Template(val) context = [self, self.__dict__['__extra_context']] return tmpl.substitute(StrWrapper(context)) return val -- cgit From 03deb0dde48a0b9c7c6c52689ecf8a70e1fa7b7e Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 29 Nov 2010 22:01:19 +0100 Subject: Adjust state_path default setting so that api unit tests find things where they used to find them. --- nova/flags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/flags.py b/nova/flags.py index 948729449..cb9fa105b 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -244,7 +244,7 @@ DEFINE_string('vpn_key_suffix', DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger') -DEFINE_string('state_path', os.path.abspath("./"), +DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'), "Top-level directory for maintaining nova's state") DEFINE_string('sql_connection', -- cgit From 2cc492240fab447a62e7ca3ea1c16744baad9256 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 29 Nov 2010 21:23:21 +0000 Subject: update of nova.sh because default flagfile moved --- contrib/nova.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/nova.sh b/contrib/nova.sh index 6033c9e3a..7407422b3 100755 --- a/contrib/nova.sh +++ b/contrib/nova.sh @@ -23,7 +23,7 @@ MYSQL_PASS=${MYSQL_PASS:-nova} TEST=${TEST:-0} USE_LDAP=${USE_LDAP:-0} LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu} -NET_MAN=${NET_MAN:-FlatDHCPManager} +NET_MAN=${NET_MAN:-VlanManager} # NOTE(vish): If you are using FlatDHCP on multiple hosts, set the interface # below but make sure that the interface doesn't already have an # ip or you risk breaking things. @@ -42,10 +42,10 @@ else fi mkdir -p /etc/nova -cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF +cat >$NOVA_DIR/bin/nova.conf << NOVA_CONF_EOF --verbose --nodaemon ---dhcpbridge_flagfile=/etc/nova/nova-manage.conf +--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf --FAKE_subdomain=ec2 --network_manager=nova.network.manager.$NET_MAN --cc_host=$HOST_IP @@ -56,7 +56,7 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF NOVA_CONF_EOF if [ -n "$FLAT_INTERFACE" ]; then - echo "--flat_interface=$FLAT_INTERFACE" >>/etc/nova/nova-manage.conf + echo "--flat_interface=$FLAT_INTERFACE" >>$NOVA_DIR/bin/nova.conf fi if [ "$CMD" == "branch" ]; then @@ -142,12 +142,12 @@ if [ "$CMD" == "run" ]; then # nova api crashes if we start it with a regular screen command, # so send the start command by forcing text into the window. - screen_it api "$NOVA_DIR/bin/nova-api --flagfile=/etc/nova/nova-manage.conf" - screen_it objectstore "$NOVA_DIR/bin/nova-objectstore --flagfile=/etc/nova/nova-manage.conf" - screen_it compute "$NOVA_DIR/bin/nova-compute --flagfile=/etc/nova/nova-manage.conf" - screen_it network "$NOVA_DIR/bin/nova-network --flagfile=/etc/nova/nova-manage.conf" - screen_it scheduler "$NOVA_DIR/bin/nova-scheduler --flagfile=/etc/nova/nova-manage.conf" - screen_it volume "$NOVA_DIR/bin/nova-volume --flagfile=/etc/nova/nova-manage.conf" + screen_it api "$NOVA_DIR/bin/nova-api" + screen_it objectstore "$NOVA_DIR/bin/nova-objectstore" + screen_it compute "$NOVA_DIR/bin/nova-compute" + screen_it network "$NOVA_DIR/bin/nova-network" + screen_it scheduler "$NOVA_DIR/bin/nova-scheduler" + screen_it volume "$NOVA_DIR/bin/nova-volume" screen_it test ". $NOVA_DIR/novarc" screen -S nova -x fi -- cgit From e6dde30724ac47f6abeb5eaa56a68fb9ac166397 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 29 Nov 2010 23:04:54 +0100 Subject: Correctly handle imageId list passed to DescribeImages API call. --- nova/api/ec2/cloud.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 9327bf0d4..9cabd2e7d 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -994,7 +994,10 @@ class CloudController(object): return True def describe_images(self, context, image_id=None, **kwargs): - imageSet = self.image_service.index(context, image_id) + # Note: image_id is a list! + imageSet = self.image_service.index(context) + if image_id: + imageSet = filter(lambda x: x['imageId'] in image_id, imageSet) return {'imagesSet': imageSet} def deregister_image(self, context, image_id, **kwargs): -- cgit From 8ee658e7f6da2484377bec7652f37df7259f9e8a Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Mon, 29 Nov 2010 17:26:05 -0600 Subject: Return the correct server_management_url --- nova/api/openstack/auth.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index ff428ff70..f91742b37 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -47,7 +47,7 @@ class BasicApiAuthManager(object): except KeyError: return faults.Fault(webob.exc.HTTPUnauthorized()) - token, user = self._authorize_user(username, key) + token, user = self._authorize_user(username, key, req) if user and token: res = webob.Response() res.headers['X-Auth-Token'] = token.token_hash @@ -82,8 +82,13 @@ class BasicApiAuthManager(object): return {'id': user.id} return None - def _authorize_user(self, username, key): - """ Generates a new token and assigns it to a user """ + def _authorize_user(self, username, key, req): + """Generates a new token and assigns it to a user. + + username - string + key - string API key + req - webob.Request object + """ user = self.auth.get_user_from_access_key(key) if user and user.name == username: token_hash = hashlib.sha1('%s%s%f' % (username, key, @@ -91,12 +96,10 @@ class BasicApiAuthManager(object): token_dict = {} token_dict['token_hash'] = token_hash token_dict['cdn_management_url'] = '' - token_dict['server_management_url'] = self._get_server_mgmt_url() + # Same as auth url, e.g. http://foo.org:8774/baz/v1.0 + token_dict['server_management_url'] = req.url token_dict['storage_url'] = '' token_dict['user_id'] = user.id token = self.db.auth_create_token(self.context, token_dict) return token, user return None, None - - def _get_server_mgmt_url(self): - return 'https://%s/v1.0/' % self.host -- cgit From e82afc902020d7bf7bc60141a629287599d8796a Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Mon, 29 Nov 2010 17:38:51 -0600 Subject: remove FAKE_subdomain reference --- contrib/nova.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/nova.sh b/contrib/nova.sh index 6033c9e3a..7f111d2b3 100755 --- a/contrib/nova.sh +++ b/contrib/nova.sh @@ -46,7 +46,6 @@ cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF --verbose --nodaemon --dhcpbridge_flagfile=/etc/nova/nova-manage.conf ---FAKE_subdomain=ec2 --network_manager=nova.network.manager.$NET_MAN --cc_host=$HOST_IP --routing_source_ip=$HOST_IP -- cgit From 6d097a220846c54cb11b4a0e480f282e50db6058 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 30 Nov 2010 09:19:32 +0100 Subject: Rename imageSet variable to images. --- nova/api/ec2/cloud.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 9cabd2e7d..884372ce7 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -995,10 +995,10 @@ class CloudController(object): def describe_images(self, context, image_id=None, **kwargs): # Note: image_id is a list! - imageSet = self.image_service.index(context) + images = self.image_service.index(context) if image_id: - imageSet = filter(lambda x: x['imageId'] in image_id, imageSet) - return {'imagesSet': imageSet} + images = filter(lambda x: x['imageId'] in image_id, images) + return {'imagesSet': images} def deregister_image(self, context, image_id, **kwargs): self.image_service.deregister(context, image_id) -- cgit From 41b3faf113d7591e61b03678dc13cd9ef031efbb Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Tue, 30 Nov 2010 10:40:17 -0500 Subject: If only I weren't so lazy. --- nova/tests/api/openstack/test_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 29f4b8874..4b75995dc 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -69,7 +69,7 @@ class Test(unittest.TestCase): self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) self.assertEqual(result.headers['X-Server-Management-Url'], - "https://foo/v1.0/") + "http://foo/v1.0/") self.assertEqual(result.headers['X-CDN-Management-Url'], "") self.assertEqual(result.headers['X-Storage-Url'], "") -- cgit From 84fdd48fe2db20661f076884810f0c726630452f Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Tue, 30 Nov 2010 13:52:46 -0500 Subject: Fix unit tests --- nova/api/openstack/auth.py | 5 +---- nova/tests/api/openstack/fakes.py | 1 - nova/tests/api/openstack/test_auth.py | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index f91742b37..205035915 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -23,10 +23,7 @@ class Context(object): class BasicApiAuthManager(object): """ Implements a somewhat rudimentary version of OpenStack Auth""" - def __init__(self, host=None, db_driver=None): - if not host: - host = FLAGS.host - self.host = host + def __init__(self, db_driver=None): if not db_driver: db_driver = FLAGS.db_driver self.db = utils.import_object(db_driver) diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 639a2ebe4..6e91ca7bb 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -54,7 +54,6 @@ def fake_auth_init(self): self.db = FakeAuthDatabase() self.context = Context() self.auth = FakeAuthManager() - self.host = 'foo' @webob.dec.wsgify diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 4b75995dc..14e720be4 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -62,7 +62,7 @@ class Test(unittest.TestCase): f = fakes.FakeAuthManager() f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) - req = webob.Request.blank('/v1.0/') + req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' req.headers['X-Auth-Key'] = 'derp' result = req.get_response(nova.api.API('os')) -- cgit From 9117146ad8b09ccd428f36efde795f8c9b989a19 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 1 Dec 2010 11:50:25 +0100 Subject: Move cc_host and cc_port flags into nova/network/linux_net.py. They weren't used anywhere else. Make cc_host default to nova.utils.get_my_ip() instead of 127.0.0.1. cc_host is used to set up forwarding to the meta-data service, and the kernel doesn't allow routing to a loopback device, so 127.0.0.1 is a poor default. --- nova/flags.py | 2 -- nova/network/linux_net.py | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index cb9fa105b..1f94feb08 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -223,8 +223,6 @@ DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host') DEFINE_integer('rabbit_retry_interval', 10, 'rabbit connection retry interval') DEFINE_integer('rabbit_max_retries', 12, 'rabbit connection attempts') DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to') -DEFINE_string('cc_host', '127.0.0.1', 'ip of api server') -DEFINE_integer('cc_port', 8773, 'cloud controller port') DEFINE_string('ec2_url', 'http://127.0.0.1:8773/services/Cloud', 'Url to ec2 api server') diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7b00e65d4..0fefd9415 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -46,6 +46,8 @@ flags.DEFINE_string('vlan_interface', 'eth0', 'network device for vlans') flags.DEFINE_string('dhcpbridge', _bin_file('nova-dhcpbridge'), 'location of nova-dhcpbridge') +flags.DEFINE_string('cc_host', utils.get_my_ip(), 'ip of api server') +flags.DEFINE_integer('cc_port', 8773, 'cloud controller port') flags.DEFINE_string('routing_source_ip', '127.0.0.1', 'Public IP of network host') flags.DEFINE_bool('use_nova_chains', False, -- cgit From 11dddd7ca4f4264ef3a8f1e251601c1d8fd7a626 Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 10:44:51 -0600 Subject: Move default_flagfile() call to where it will be parsed in time to load the flagfile --- bin/nova-compute | 3 ++- bin/nova-instancemonitor | 2 +- bin/nova-network | 2 +- bin/nova-objectstore | 2 +- bin/nova-scheduler | 2 +- bin/nova-volume | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/bin/nova-compute b/bin/nova-compute index a66477af5..1054852c4 100755 --- a/bin/nova-compute +++ b/bin/nova-compute @@ -38,8 +38,9 @@ from nova import utils if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() application = service.Service.create() # pylint: disable=C0103 + diff --git a/bin/nova-instancemonitor b/bin/nova-instancemonitor index a7b7fb0c6..9b6c40e82 100755 --- a/bin/nova-instancemonitor +++ b/bin/nova-instancemonitor @@ -42,10 +42,10 @@ logging.getLogger('boto').setLevel(logging.WARN) if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() logging.warn('Starting instance monitor') # pylint: disable-msg=C0103 monitor = monitor.InstanceMonitor() diff --git a/bin/nova-network b/bin/nova-network index 342a63058..d1fb55261 100755 --- a/bin/nova-network +++ b/bin/nova-network @@ -38,8 +38,8 @@ from nova import utils if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() application = service.Service.create() # pylint: disable-msg=C0103 diff --git a/bin/nova-objectstore b/bin/nova-objectstore index 728f2ee5b..00ae27af9 100755 --- a/bin/nova-objectstore +++ b/bin/nova-objectstore @@ -42,8 +42,8 @@ FLAGS = flags.FLAGS if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() application = handler.get_application() # pylint: disable-msg=C0103 diff --git a/bin/nova-scheduler b/bin/nova-scheduler index 069b5a6fa..4d1a40cf1 100755 --- a/bin/nova-scheduler +++ b/bin/nova-scheduler @@ -38,8 +38,8 @@ from nova import utils if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() application = service.Service.create() diff --git a/bin/nova-volume b/bin/nova-volume index 26148b0ec..e7281d6c0 100755 --- a/bin/nova-volume +++ b/bin/nova-volume @@ -38,8 +38,8 @@ from nova import utils if __name__ == '__main__': + utils.default_flagfile() twistd.serve(__file__) if __name__ == '__builtin__': - utils.default_flagfile() application = service.Service.create() # pylint: disable-msg=C0103 -- cgit From 6e6b5325bfc5233b243ed9f8279694136d605ddf Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 11:43:20 -0600 Subject: Removed a blank line. --- bin/nova-compute | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/nova-compute b/bin/nova-compute index 1054852c4..ac6378f75 100755 --- a/bin/nova-compute +++ b/bin/nova-compute @@ -43,4 +43,3 @@ if __name__ == '__main__': if __name__ == '__builtin__': application = service.Service.create() # pylint: disable=C0103 - -- cgit From 93c7bbf98f0396718724cbf1d4d2f3953078776c Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 14:18:24 -0600 Subject: Remove duplicate field and make OpenStack API return server.name for EC2-API-created instances --- nova/api/openstack/servers.py | 5 ++--- nova/db/sqlalchemy/models.py | 3 +-- nova/tests/api/openstack/test_servers.py | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 1d8aa2fa4..44e69b82c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -63,7 +63,7 @@ def _entity_detail(inst): inst_dict = {} mapped_keys = dict(status='state', imageId='image_id', - flavorId='instance_type', name='server_name', id='id') + flavorId='instance_type', name='display_name', id='id') for k, v in mapped_keys.iteritems(): inst_dict[k] = inst[v] @@ -78,7 +78,7 @@ def _entity_detail(inst): def _entity_inst(inst): """ Filters all model attributes save for id and name """ - return dict(server=dict(id=inst['id'], name=inst['server_name'])) + return dict(server=dict(id=inst['id'], name=inst['display_name'])) class Controller(wsgi.Controller): @@ -213,7 +213,6 @@ class Controller(wsgi.Controller): if not image: raise Exception("Image not found") - inst['server_name'] = env['server']['name'] inst['image_id'] = image_id inst['user_id'] = user_id inst['launch_time'] = ltime diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 01b5cf350..fe0a9a921 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -178,8 +178,6 @@ class Instance(BASE, NovaBase): kernel_id = Column(String(255)) ramdisk_id = Column(String(255)) - server_name = Column(String(255)) - # image_id = Column(Integer, ForeignKey('images.id'), nullable=True) # kernel_id = Column(Integer, ForeignKey('images.id'), nullable=True) # ramdisk_id = Column(Integer, ForeignKey('images.id'), nullable=True) @@ -212,6 +210,7 @@ class Instance(BASE, NovaBase): launched_at = Column(DateTime) terminated_at = Column(DateTime) + # User editable field for display in user-facing UIs display_name = Column(String(255)) display_description = Column(String(255)) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 8cfc6c45a..530d06760 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -44,7 +44,7 @@ def return_servers(context, user_id=1): def stub_instance(id, user_id=1): - return Instance(id=id, state=0, image_id=10, server_name='server%s' % id, + return Instance(id=id, state=0, image_id=10, display_name='server%s' % id, user_id=user_id) -- cgit From fdf0aa30a1127eb8311a599dfdad9653ac699154 Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 14:55:42 -0600 Subject: Todd points out that the API doesn't require a display_name, so let's make a default. That way the OpenStack API can rest assured that its server responses will always have a name key. --- nova/compute/manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 50a9d316b..0893db9fc 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -99,6 +99,8 @@ class ComputeManager(manager.Manager): that has just been created """ + # Set sane defaults if not specified + kwargs.setdefault('display_name', "Server %s" % kwargs['internal_id']) instance_ref = self.db.instance_create(context, kwargs) inst_id = instance_ref['id'] -- cgit From f53f5880c08994d04a552a41ce6f88dfbd867946 Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 15:53:27 -0600 Subject: Oops, internal_id isn't available until after a save. This code saves twice; if I moved it into the DB layer we could do it in one save. However, we're moving to one sqlite db per compute worker, so I'd rather have two saves in order to keep the logic in the right layer. --- nova/compute/manager.py | 8 ++++++-- nova/db/sqlalchemy/api.py | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0893db9fc..6fc5c5186 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -99,10 +99,14 @@ class ComputeManager(manager.Manager): that has just been created """ - # Set sane defaults if not specified - kwargs.setdefault('display_name', "Server %s" % kwargs['internal_id']) instance_ref = self.db.instance_create(context, kwargs) inst_id = instance_ref['id'] + # Set sane defaults if not specified + if 'display_name' not in kwargs: + display_name = "Server %s" % instance_ref['internal_id'] + instance_ref['display_name'] = display_name + self.db.instance_update(context, inst_id, + { 'display_name': display_name }) elevated = context.elevated() if not security_groups: diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index afa55fc03..dd9649054 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -530,6 +530,12 @@ def fixed_ip_update(context, address, values): #functions between the two of them as well. @require_context def instance_create(context, values): + """Create a new Instance record in the database. + + context - request context object + values - dict containing column values. + 'internal_id' is auto-generated and should not be specified. + """ instance_ref = models.Instance() instance_ref.update(values) -- cgit From 8af2b1c97903f11034a95894a23bb7e77f573aa6 Mon Sep 17 00:00:00 2001 From: Michael Gundlach Date: Wed, 1 Dec 2010 16:04:04 -0600 Subject: Going for a record commits per line changes ratio --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 6fc5c5186..e826bdaa2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -106,7 +106,7 @@ class ComputeManager(manager.Manager): display_name = "Server %s" % instance_ref['internal_id'] instance_ref['display_name'] = display_name self.db.instance_update(context, inst_id, - { 'display_name': display_name }) + {'display_name': display_name}) elevated = context.elevated() if not security_groups: -- cgit