Merge remote branch 'nova/master'

This commit is contained in:
Vishvananda Ishaya
2010-06-11 10:08:40 -07:00
6 changed files with 101 additions and 82 deletions

View File

@@ -71,15 +71,35 @@ class UserCommands(object):
for user in self.manager.get_users():
print user.name
def zip(self, name, filename='nova.zip'):
class ProjectCommands(object):
def __init__(self):
self.manager = users.UserManager.instance()
def create(self, name, project_manager, description=None):
"""creates a new project
arguments: name project_manager [description]"""
user = self.manager.create_project(name, project_manager, description)
def delete(self, name):
"""deletes an existing project
arguments: name"""
self.manager.delete_project(name)
def list(self):
"""lists all projects
arguments: <none>"""
for project in self.manager.get_projects():
print project.name
def zip(self, project_id, user_id, filename='nova.zip'):
"""exports credentials for user to a zip file
arguments: name [filename='nova.zip]"""
user = self.manager.get_user(name)
if user:
arguments: project_id user_id [filename='nova.zip]"""
project = self.manager.get_project(project_id)
if project:
with open(filename, 'w') as f:
f.write(user.get_credentials())
f.write(project.get_credentials(user_id))
else:
print "User %s doesn't exist" % name
print "Project %s doesn't exist" % project
def usage(script_name):
@@ -88,6 +108,7 @@ def usage(script_name):
categories = [
('user', UserCommands),
('project', ProjectCommands),
]

View File

@@ -1,11 +1,11 @@
# Copyright [2010] [Anso Labs, LLC]
#
#
# 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.
@@ -13,7 +13,7 @@
# limitations under the License.
NOVA_KEY_DIR=$(pushd $(dirname $BASH_SOURCE)>/dev/null; pwd; popd>/dev/null)
export EC2_ACCESS_KEY="%(access)s"
export EC2_ACCESS_KEY="%(access)s:%(project)s"
export EC2_SECRET_KEY="%(secret)s"
export EC2_URL="%(ec2)s"
export S3_URL="%(s3)s"

View File

@@ -93,9 +93,12 @@ class User(AuthBase):
def is_project_manager(self, project):
return UserManager.instance().is_project_manager(self, project)
def generate_rc(self):
def generate_rc(self, project=None):
if project is None:
project = self.id
rc = open(FLAGS.credentials_template).read()
rc = rc % { 'access': self.access,
'project': project,
'secret': self.secret,
'ec2': FLAGS.ec2_url,
's3': 'http://%s:%s' % (FLAGS.s3_host, FLAGS.s3_port),
@@ -168,7 +171,9 @@ class Project(Group):
return User.safe_id(user) == self.project_manager_id
def get_credentials(self, user):
rc = user.generate_rc()
if not isinstance(user, User):
user = UserManager.instance().get_user(user)
rc = user.generate_rc(self.id)
private_key, signed_cert = self.generate_x509_cert(user)
tmpdir = tempfile.mkdtemp()
@@ -238,7 +243,7 @@ class UserManager(object):
raise exception.NotAuthorized('Signature does not match')
return (user, project)
def create_project(self, name, manager_user, description, member_users=None):
def create_project(self, name, manager_user, description=None, member_users=None):
if member_users:
member_users = [User.safe_id(u) for u in member_users]
with LDAPWrapper() as conn:
@@ -462,12 +467,15 @@ class LDAPWrapper(object):
self.conn.add_s(self.__uid_to_dn(name), attr)
return self.__to_user(dict(attr))
def create_project(self, name, manager_uid, description, member_uids = None):
def create_project(self, name, manager_uid, description=None, member_uids=None):
if self.project_exists(name):
raise exception.Duplicate("Project can't be created because project %s already exists" % name)
if not self.user_exists(manager_uid):
raise exception.NotFound("Project can't be created because manager %s doesn't exist" % manager_uid)
manager_dn = self.__uid_to_dn(manager_uid)
# description is a required attribute
if description is None:
description = name
members = []
if member_uids != None:
for member_uid in member_uids:

View File

@@ -28,6 +28,7 @@ import json
import logging
import os
import sqlite3
import time
from nova import vendor
import redis
@@ -77,10 +78,11 @@ class RedisModel(object):
def set_default_state(self):
self.state = {'state' : 'pending'}
self.state[self.object_type+"_id"] = self.object_id
self.state["create_time"] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
@property
def __redis_key(self):
""" Magic string for instance keys """
""" Magic string for keys """
return '%s:%s' % (self.object_type, self.object_id)
def __repr__(self):

View File

@@ -60,7 +60,7 @@ class CloudController(object):
"""
def __init__(self):
self.instdir = model.InstanceDirectory()
self.network = network.NetworkController()
self.network = network.PublicNetworkController()
self.setup()
@property
@@ -254,21 +254,10 @@ class CloudController(object):
res.addCallback(_format_result)
return res
def _convert_address(self, network_address):
# FIXME(vish): this should go away when network.py stores info properly
address = {}
address['public_ip'] == network_address[u'address']
address['user_id'] == network_address[u'user_id']
address['project_id'] == network_address.get(u'project_id', address['user_id'])
address['instance_id'] == network_address.get(u'instance_id', None)
return address
def _get_address(self, context, public_ip):
# right now all addresses are allocated locally
# FIXME(vish) this should move into network.py
for network_address in self.network.describe_addresses():
if network_address[u'address'] == public_ip:
address = self._convert_address(network_address)
for address in self.network.hosts:
if address['address'] == public_ip:
if context.user.is_admin() or address['project_id'] == context.project.id:
return address
raise exception.NotFound("Address at ip %s not found" % public_ip)
@@ -398,14 +387,12 @@ class CloudController(object):
def format_addresses(self, context):
addresses = []
# TODO(vish): move authorization checking into network.py
for network_address in self.network.describe_addresses(type=network.PublicNetwork):
for address in self.network.hosts:
#logging.debug(address_record)
address = self._convert_address(network_address)
address_rv = {
'public_ip': address['public_ip'],
'public_ip': address['address'],
'instance_id' : address.get('instance_id', 'free')
}
# FIXME: add another field for user id
if context.user.is_admin():
address_rv['instance_id'] = "%s (%s, %s)" % (
address['instance_id'],
@@ -417,17 +404,17 @@ class CloudController(object):
return {'addressesSet': addresses}
def allocate_address(self, context, **kwargs):
(address,network_name) = self.network.allocate_address(
context.user.id, context.project_id, type=network.PublicNetwork)
address = self.network.allocate_ip(
context.user.id, context.project.id, 'public')
return defer.succeed({'addressSet': [{'publicIp' : address}]})
def release_address(self, context, public_ip, **kwargs):
address = self._get_address(public_ip)
self.network.deallocate_ip(public_ip)
return defer.succeed({'releaseResponse': ["Address released."]})
def associate_address(self, context, instance_id, **kwargs):
instance = self._get_instance(context, instance_id)
rv = self.network.associate_address(
self.network.associate_address(
kwargs['public_ip'],
instance['private_dns_name'],
instance_id)
@@ -435,7 +422,7 @@ class CloudController(object):
def disassociate_address(self, context, public_ip, **kwargs):
address = self._get_address(public_ip)
rv = self.network.disassociate_address(public_ip)
self.network.disassociate_address(public_ip)
# TODO - Strip the IP from the instance
return defer.succeed({'disassociateResponse': ["Address disassociated."]})
@@ -466,14 +453,10 @@ class CloudController(object):
inst['project_id'] = context.project.id
inst['mac_address'] = utils.generate_mac()
inst['ami_launch_index'] = num
address, _netname = self.network.allocate_address(
user_id=inst['user_id'],
project_id=inst['project_id'],
mac=inst['mac_address'])
network = self.network.get_users_network(str(context.user.id))
inst['network_str'] = json.dumps(network.to_dict())
inst['bridge_name'] = network.bridge_name
address = network.allocate_ip(
inst['user_id'], inst['project_id'], mac=inst['mac_address'])
inst['private_dns_name'] = str(address)
inst['bridge_name'] = network.BridgedNetwork.get_network_for_project(inst['user_id'], inst['project_id'])['bridge_name']
# TODO: allocate expresses on the router node
inst.save()
rpc.cast(FLAGS.compute_topic,
@@ -502,7 +485,7 @@ class CloudController(object):
if instance.get('private_dns_name', None):
logging.debug("Deallocating address %s" % instance.get('private_dns_name', None))
try:
self.network.deallocate_address(instance.get('private_dns_name', None))
self.network.deallocate_ip(instance.get('private_dns_name', None))
except Exception, _err:
pass
if instance.get('node_name', 'unassigned') != 'unassigned': #It's also internal default

View File

@@ -23,11 +23,17 @@ from nova import flags
from nova import test
from nova.compute import network
from nova.auth import users
from nova import utils
class NetworkTestCase(test.TrialTestCase):
def setUp(self):
super(NetworkTestCase, self).setUp()
self.flags(fake_libvirt=True,
fake_storage=True,
fake_network=True,
network_size=32,
redis_db=8)
logging.getLogger().setLevel(logging.DEBUG)
self.manager = users.UserManager.instance()
try:
@@ -37,7 +43,7 @@ class NetworkTestCase(test.TrialTestCase):
name = 'project%s' % i
if not self.manager.get_project(name):
self.manager.create_project(name, 'netuser', name)
self.network = network.NetworkController(netsize=16)
self.network = network.PublicNetworkController()
def tearDown(self):
super(NetworkTestCase, self).tearDown()
@@ -46,70 +52,69 @@ class NetworkTestCase(test.TrialTestCase):
self.manager.delete_project(name)
self.manager.delete_user('netuser')
def test_network_serialization(self):
net1 = network.Network(vlan=100, network="192.168.100.0/24", conn=None)
address = net1.allocate_ip("netuser", "project0", "01:24:55:36:f2:a0")
net_json = str(net1)
net2 = network.Network.from_json(net_json)
self.assertEqual(net_json, str(net2))
self.assertTrue(IPy.IP(address) in net2.network)
def test_public_network_allocation(self):
pubnet = IPy.IP(flags.FLAGS.public_range)
address = self.network.allocate_ip("netuser", "project0", "public")
self.assertTrue(IPy.IP(address) in pubnet)
self.assertTrue(IPy.IP(address) in self.network.network)
def test_allocate_deallocate_address(self):
(address, net_name) = self.network.allocate_address("netuser",
"project0", "01:24:55:36:f2:a0")
def test_allocate_deallocate_ip(self):
address = network.allocate_ip(
"netuser", "project0", utils.generate_mac())
logging.debug("Was allocated %s" % (address))
self.assertEqual(True, address in self._get_project_addresses("project0"))
rv = self.network.deallocate_address(address)
rv = network.deallocate_ip(address)
self.assertEqual(False, address in self._get_project_addresses("project0"))
def test_range_allocation(self):
(address, net_name) = self.network.allocate_address("netuser",
"project0", "01:24:55:36:f2:a0")
(secondaddress, net_name) = self.network.allocate_address("netuser",
"project1", "01:24:55:36:f2:a0")
self.assertEqual(True, address in self._get_project_addresses("project0"))
address = network.allocate_ip(
"netuser", "project0", utils.generate_mac())
secondaddress = network.allocate_ip(
"netuser", "project1", utils.generate_mac())
self.assertEqual(True,
address in self._get_project_addresses("project0"))
self.assertEqual(True,
secondaddress in self._get_project_addresses("project1"))
self.assertEqual(False, address in self._get_project_addresses("project1"))
rv = self.network.deallocate_address(address)
rv = network.deallocate_ip(address)
self.assertEqual(False, address in self._get_project_addresses("project0"))
rv = self.network.deallocate_address(secondaddress)
rv = network.deallocate_ip(secondaddress)
self.assertEqual(False,
secondaddress in self._get_project_addresses("project1"))
def test_subnet_edge(self):
(secondaddress, net_name) = self.network.allocate_address("netuser", "project0")
secondaddress = network.allocate_ip("netuser", "project0",
utils.generate_mac())
for project in range(1,5):
project_id = "project%s" % (project)
(address, net_name) = self.network.allocate_address("netuser",
project_id, "01:24:55:36:f2:a0")
(address2, net_name) = self.network.allocate_address("netuser",
project_id, "01:24:55:36:f2:a0")
(address3, net_name) = self.network.allocate_address("netuser",
project_id, "01:24:55:36:f2:a0")
address = network.allocate_ip(
"netuser", project_id, utils.generate_mac())
address2 = network.allocate_ip(
"netuser", project_id, utils.generate_mac())
address3 = network.allocate_ip(
"netuser", project_id, utils.generate_mac())
self.assertEqual(False,
address in self._get_project_addresses("project0"))
self.assertEqual(False,
address2 in self._get_project_addresses("project0"))
self.assertEqual(False,
address3 in self._get_project_addresses("project0"))
rv = self.network.deallocate_address(address)
rv = self.network.deallocate_address(address2)
rv = self.network.deallocate_address(address3)
rv = self.network.deallocate_address(secondaddress)
rv = network.deallocate_ip(address)
rv = network.deallocate_ip(address2)
rv = network.deallocate_ip(address3)
rv = network.deallocate_ip(secondaddress)
def test_too_many_projects(self):
for i in range(0, 30):
name = 'toomany-project%s' % i
self.manager.create_project(name, 'netuser', name)
(address, net_name) = self.network.allocate_address("netuser",
name, "01:24:55:36:f2:a0")
address = network.allocate_ip(
"netuser", name, utils.generate_mac())
rv = network.deallocate_ip(address)
self.manager.delete_project(name)
def _get_project_addresses(self, project_id):
rv = self.network.describe_addresses()
project_addresses = []
for item in rv:
if item['project_id'] == project_id:
project_addresses.append(item['address'])
for addr in network.get_project_network(project_id).list_addresses():
project_addresses.append(addr)
return project_addresses