added security group to create cluster call

- Added a configuration item, os_security_group, to api to allow
  a default security group to be specified
- Added tests to test_create_vm to verify invalid security group
  results in a failure
- Modified nova fixture to check for security_groups in vm create
- Modified neutron create port to include security_groups
- Modified devstack plugin to create a security group for rabbitmq

Change-Id: Ib8490b15b0e90812d630d237cc4fcc8d0c8a4f9a
This commit is contained in:
Min Pae 2015-02-23 17:36:25 -08:00
parent 96352937d5
commit 85c84945c8
10 changed files with 106 additions and 25 deletions

View File

@ -48,6 +48,9 @@ CUE_SERVICE_PROTOCOL=${CUE_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
CUE_SERVICE_HOST=${CUE_SERVICE_HOST:-$SERVICE_HOST}
CUE_SERVICE_PORT=${CUE_SERVICE_PORT:-8795}
CUE_MANAGEMENT_KEY='cue-mgmt-key'
CUE_RABBIT_SECURITY_GROUP='cue-rabbitmq'
UBUNTU_IMAGE_NAME='ubuntu-14.04-server'
UBUNTU_IMAGE_URL='https://cloud-images.ubuntu.com/releases/14.04/release-20150305/ubuntu-14.04-server-cloudimg-amd64-disk1.img'
UBUNTU_IMAGE_MD5='00662c59ca52558e7a3bb9a67d194730'
@ -190,6 +193,22 @@ function init_cue {
if [ "$UBUNTU_IMAGE_ID" ]; then
iniset $CUE_CONF api os_image_id $UBUNTU_IMAGE_ID
fi
# Set os_security_group
if [[ -z $($OPENSTACK_CMD security group list | grep $CUE_RABBIT_SECURITY_GROUP) ]]; then
$OPENSTACK_CMD security group create $CUE_RABBIT_SECURITY_GROUP
$OPENSTACK_CMD security group rule create --src-ip 0.0.0.0/0 --proto tcp --dst-port 5672:5672 $CUE_RABBIT_SECURITY_GROUP
fi
CUE_RABBIT_SECURITY_GROUP_ID=$($OPENSTACK_CMD security group list | grep $CUE_RABBIT_SECURITY_GROUP | tr -d ' ' | cut -f 2 -d '|')
if [ $CUE_RABBIT_SECURITY_GROUP_ID ]; then
iniset $CUE_CONF DEFAULT os_security_group $CUE_RABBIT_SECURITY_GROUP_ID
fi
# Set VM management key
if [ $CUE_MANAGEMENT_KEY ]; then
iniset $CUE_CONF openstack os_key_name $CUE_MANAGEMENT_KEY
fi
}
# install_cue - Collect source and prepare

View File

@ -11,6 +11,8 @@ RABBIT_PASSWORD=password
SERVICE_PASSWORD=password
SERVICE_TOKEN=password
CUE_MANAGEMENT_KEY_NAME=cue-mgmt-key
# Enable Logging
LOGFILE=/opt/stack/logs/stack.sh.log
VERBOSE=True

View File

@ -30,6 +30,10 @@ if [[ ! -f ~/.ssh/id_rsa ]]; then
ssh-keygen -q -t rsa -N "" -f ~/.ssh/id_rsa
fi
if [[ -z $CUE_MANAGEMENT_KEY ]]; then
CUE_MANAGEMENT_KEY='vagrant'
fi
# Add ssh keypair to admin account
if [[ -z $(nova keypair-list | grep vagrant) ]]; then
nova keypair-add --pub-key ~/.ssh/id_rsa.pub vagrant
@ -44,7 +48,7 @@ neutron subnet-update --dns-nameserver 8.8.8.8 private-subnet
# Add ssh keypair to demo account
source $TOP_DIR/openrc demo demo
if [[ -z $(nova keypair-list | grep vagrant) ]]; then
nova keypair-add --pub-key ~/.ssh/id_rsa.pub vagrant
if [[ -z $(nova keypair-list | grep $CUE_MANAGEMENT_KEY) ]]; then
nova keypair-add --pub-key ~/.ssh/id_rsa.pub $CUE_MANAGEMENT_KEY
fi

View File

@ -14,6 +14,10 @@ EOF
test -d devstack || git clone https://git.openstack.org/openstack-dev/devstack
test -d /home/vagrant/bin || mkdir /home/vagrant/bin
cat << EOF > /home/vagrant/bin/refresh_devstack.sh
#!/bin/bash
rsync -av --exclude='.tox' --exclude='.venv' --exclude='.vagrant' /home/vagrant/cue /opt/stack
if [ -f "/home/vagrant/python-cueclient" ]; then
@ -30,12 +34,23 @@ if [ ! -f "/home/vagrant/devstack/local.sh" ]; then
cp /opt/stack/cue/contrib/devstack/local.sh /home/vagrant/devstack/local.sh
fi
pushd /home/vagrant/cue/contrib/devstack
for f in extras.d/* lib/*; do
if [ ! -f "/home/vagrant/devstack/$f" ]; then
ln -fs /opt/stack/cue/contrib/devstack/$f -t /home/vagrant/devstack/$(dirname $f)
if [ ! -f "/home/vagrant/devstack/\\$f" ]; then
ln -fs /opt/stack/cue/contrib/devstack/\\$f -t /home/vagrant/devstack/\\$(dirname \\$f)
fi
done
popd
EOF
chmod +x /home/vagrant/bin/refresh_devstack.sh
cat << EOF >> /home/vagrant/.bash_aliases
alias refresh_devstack="/home/vagrant/bin/refresh_devstack.sh"
EOF
/home/vagrant/bin/refresh_devstack.sh
SCRIPT

View File

@ -26,5 +26,9 @@ cfg.CONF.register_opts([
'../')),
help='Directory where the cue python module is installed'),
cfg.StrOpt('state-path', default='/var/lib/cue',
help='Top-level directory for maintaining cue\'s state')
help='Top-level directory for maintaining cue\'s state'),
cfg.StrOpt('os_security_group',
default='default',
help='The default Security Group to use for VMs created as '
'part of a cluster')
])

View File

@ -30,7 +30,8 @@ API_SERVICE_OPTS = [
'response from a collection resource.'),
# TODO(sputnik13): this needs to be removed when image selection is done
cfg.StrOpt('os_image_id',
help='The Image ID to use for VMs created as part of a cluster')
help='The Image ID to use for VMs created as part of a '
'cluster')
]
CONF = cfg.CONF

View File

@ -238,13 +238,18 @@ class ClusterController(rest.RestController):
}
job_args = {
"flavor": cluster.cluster.flavor,
'flavor': cluster.cluster.flavor,
# TODO(sputnik13): need to remove this when image selector is done
"image": CONF.api.os_image_id,
"volume_size": cluster.cluster.volume_size,
"network_id": cluster.cluster.network_id,
"port": "5672",
"context": context.to_dict(),
'image': CONF.api.os_image_id,
'volume_size': cluster.cluster.volume_size,
'network_id': cluster.cluster.network_id,
'port': '5672',
'context': context.to_dict(),
'cluster_status': 'BUILDING',
# TODO(sputnik13: this needs to come from the create request and
# default to a configuration value rather than always using config
# value
'security_groups': [CONF.os_security_group],
}
job_client = task_flow_client.get_client_instance()
#TODO(dagnello): might be better to use request_id for job_uuid

View File

@ -83,7 +83,7 @@ class CreateVmTests(base.TestCase):
self.assertEqual(self.new_vm_name, new_vm.name)
def test_create_vm_invalid_flavor(self):
invalid_flavor = uuid.uuid4()
invalid_flavor = str(uuid.uuid4())
flow_store = {
'vm_name': self.new_vm_name,
'image': self.valid_image,
@ -97,7 +97,7 @@ class CreateVmTests(base.TestCase):
self.flow, store=flow_store)
def test_create_vm_invalid_image(self):
invalid_image = uuid.uuid4()
invalid_image = str(uuid.uuid4())
flow_store = {
'vm_name': self.new_vm_name,
'image': invalid_image,
@ -111,13 +111,13 @@ class CreateVmTests(base.TestCase):
self.flow, store=flow_store)
def test_create_vm_invalid_nic(self):
invalid_nic = uuid.uuid4()
invalid_nic = str(uuid.uuid4())
flow_store = {
'vm_name': self.new_vm_name,
'image': self.valid_image,
'flavor': self.valid_flavor,
'nics': [{
'net-id': invalid_nic.hex
'net-id': invalid_nic
}]
}
@ -131,6 +131,20 @@ class CreateVmTests(base.TestCase):
self.assertRaises(taskflow_exc.MissingDependencies,
engines.run, self.flow, store=flow_store)
def test_invalid_security_group(self):
invalid_security_group = str(uuid.uuid4())
flow_store = {
'vm_name': self.new_vm_name,
'image': self.valid_image.id,
'flavor': self.valid_flavor.id,
'security_groups': [invalid_security_group],
'nics': [{
'net-id': self.valid_network['id']
}],
}
self.assertRaises(nova_exc.BadRequest, engines.run,
self.flow, store=flow_store)
def tearDown(self):
if self.new_vm_id is not None:
self.nova_client.servers.delete(self.new_vm_id)

View File

@ -105,7 +105,8 @@ class NovaClient(base.BaseFixture):
"""
def __init__(self, image_list=None, flavor_list=None,
vm_limit=None, *args, **kwargs):
vm_limit=None, security_group_list=None,
*args, **kwargs):
super(NovaClient, self).__init__(*args, **kwargs)
self._vm_list = dict()
self._image_list = dict()
@ -117,6 +118,9 @@ class NovaClient(base.BaseFixture):
if not flavor_list:
flavor_list = ['m1.tiny']
if not security_group_list:
security_group_list = []
self._vm_limit = vm_limit if vm_limit else 3
for image in image_list:
@ -131,6 +135,8 @@ class NovaClient(base.BaseFixture):
flavor_detail.id: flavor_detail
})
self._security_group_list = security_group_list
def setUp(self):
"""Set up test fixture and apply all method overrides."""
super(NovaClient, self).setUp()
@ -144,7 +150,8 @@ class NovaClient(base.BaseFixture):
v2_client.images.list = self.list_images
v2_client.flavors.find = self.find_flavors
def create_vm(self, name, image, flavor, nics=None, **kwargs):
def create_vm(self, name, image, flavor, nics=None, security_groups=None,
**kwargs):
"""Mock'd version of novaclient...create_vm().
Create a Nova VM.
@ -165,25 +172,30 @@ class NovaClient(base.BaseFixture):
except AttributeError:
image_id = image
if not self._flavor_list.get(flavor_id):
if flavor_id not in self._flavor_list:
raise nova_exc.BadRequest(400)
if not self._image_list.get(image_id):
if image_id not in self._image_list:
raise nova_exc.BadRequest(400)
if nics is not None:
neutron_client = client.neutron_client()
for nic in nics:
if nic.get('net-id'):
if 'net-id' in nic:
network_list = neutron_client.list_networks(
id=nic['net-id'])
if (not network_list or
not network_list.get('networks') or
'networks' not in network_list or
len(network_list['networks']) == 0):
raise nova_exc.BadRequest(400)
if nic.get('port-id'):
if 'port-id' in nic:
pass
if security_groups is not None:
missing = set(security_groups) - set(self._security_group_list)
if missing:
raise nova_exc.BadRequest(400)
newVm = VmDetails(vm_id=uuid.uuid4(), name=name,
flavor=flavor, image=image,
status='BUILDING')

View File

@ -32,13 +32,15 @@ class CreatePort(os_tasklib.BaseTask):
"""
default_provides = 'neutron_port_id'
def execute(self, network_id, port_name, **kwargs):
def execute(self, network_id, port_name, security_groups=None, **kwargs):
"""Main execute method
:param network_id: Network id to connect new port to
:type network_id: string
:param port_name: Name for new port
:type port_name: string
:param security_groups: Security groups to apply to new port
:type security_groups: list
:return: Port record provided by Neutron
:rtype: dict
"""
@ -50,6 +52,9 @@ class CreatePort(os_tasklib.BaseTask):
}
}
if security_groups:
body_value['port']['security_groups'] = security_groups
port = self.os_client.create_port(body=body_value)
return port