Merge "Add Neutron support"

This commit is contained in:
Jenkins 2014-02-03 18:03:37 +00:00 committed by Gerrit Code Review
commit 312244d451
11 changed files with 101 additions and 28 deletions

View File

@ -85,6 +85,12 @@ volume = {
}
}
nics = {
"type": "array",
"items": {
"type": "object",
}
}
databases_ref_list = {
"type": "array",
@ -199,7 +205,8 @@ instance = {
"type": non_empty_string,
"version": non_empty_string
}
}
},
"nics": nics
}
}
}

View File

@ -238,6 +238,11 @@ common_opts = [
default=['atom', 'json', 'xml'],
help='Filetype endings not to be reattached to an id '
'by the utils method correct_id_with_req.'),
cfg.ListOpt('default_neutron_networks',
default=[],
help='List of network IDs which should be attached'
' to instance when networks are not specified'
' in API call.'),
]
CONF = cfg.CONF

View File

@ -451,7 +451,7 @@ class Instance(BuiltInstance):
@classmethod
def create(cls, context, name, flavor_id, image_id, databases, users,
datastore, datastore_version, volume_size, backup_id,
availability_zone=None):
availability_zone=None, nics=None):
client = create_nova_client(context)
try:
@ -481,6 +481,11 @@ class Instance(BuiltInstance):
raise exception.BackupFileNotFound(
location=backup_info.location)
if not nics and CONF.default_neutron_networks:
nics = []
for net_id in CONF.default_neutron_networks:
nics.append({"net-id": net_id})
def _create_resources():
db_info = DBInstance.create(name=name, flavor_id=flavor_id,
@ -513,7 +518,7 @@ class Instance(BuiltInstance):
datastore_version.packages,
volume_size, backup_id,
availability_zone,
root_password)
root_password, nics)
return SimpleInstance(context, db_info, service_status,
root_password)

View File

@ -215,11 +215,16 @@ class InstanceController(wsgi.Controller):
else:
availability_zone = None
if 'nics' in body['instance']:
nics = body['instance']['nics']
else:
nics = None
instance = models.Instance.create(context, name, flavor_id,
image_id, databases, users,
datastore, datastore_version,
volume_size, backup_id,
availability_zone)
availability_zone, nics)
view = views.InstanceDetailView(instance, req=req)
return wsgi.Result(view.data(), 200)

View File

@ -102,7 +102,7 @@ class API(proxy.RpcProxy):
def create_instance(self, instance_id, name, flavor,
image_id, databases, users, datastore_manager,
packages, volume_size, backup_id=None,
availability_zone=None, root_password=None):
availability_zone=None, root_password=None, nics=None):
LOG.debug("Making async call to create instance %s " % instance_id)
self.cast(self.context,
self.make_msg("create_instance",
@ -117,4 +117,4 @@ class API(proxy.RpcProxy):
volume_size=volume_size,
backup_id=backup_id,
availability_zone=availability_zone,
root_password=root_password))
root_password=root_password, nics=nics))

View File

@ -83,12 +83,12 @@ class Manager(periodic_task.PeriodicTasks):
def create_instance(self, context, instance_id, name, flavor,
image_id, databases, users, datastore_manager,
packages, volume_size, backup_id, availability_zone,
root_password):
root_password, nics):
instance_tasks = FreshInstanceTasks.load(context, instance_id)
instance_tasks.create_instance(flavor, image_id, databases, users,
datastore_manager, packages,
volume_size, backup_id,
availability_zone, root_password)
availability_zone, root_password, nics)
if CONF.exists_notification_transformer:
@periodic_task.periodic_task(

View File

@ -147,7 +147,7 @@ class ConfigurationMixin(object):
class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
def create_instance(self, flavor, image_id, databases, users,
datastore_manager, packages, volume_size,
backup_id, availability_zone, root_password):
backup_id, availability_zone, root_password, nics):
LOG.debug(_("begin create_instance for id: %s") % self.id)
security_groups = None
@ -175,7 +175,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
image_id,
datastore_manager,
volume_size,
availability_zone)
availability_zone,
nics)
elif use_nova_server_volume:
volume_info = self._create_server_volume(
flavor['id'],
@ -183,7 +184,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
security_groups,
datastore_manager,
volume_size,
availability_zone)
availability_zone,
nics)
else:
volume_info = self._create_server_volume_individually(
flavor['id'],
@ -191,7 +193,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
security_groups,
datastore_manager,
volume_size,
availability_zone)
availability_zone,
nics)
config = self._render_config(datastore_manager, flavor, self.id)
@ -302,7 +305,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
def _create_server_volume(self, flavor_id, image_id, security_groups,
datastore_manager, volume_size,
availability_zone):
availability_zone, nics):
LOG.debug(_("begin _create_server_volume for id: %s") % self.id)
server = None
try:
@ -321,7 +324,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
name, image_id, flavor_id,
files=files, volume=volume_ref,
security_groups=security_groups,
availability_zone=availability_zone)
availability_zone=availability_zone, nics=nics)
LOG.debug(_("Created new compute instance %(server_id)s "
"for id: %(id)s") %
{'server_id': server.id, 'id': self.id})
@ -349,14 +352,16 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
def _create_server_volume_heat(self, flavor, image_id,
datastore_manager,
volume_size, availability_zone):
volume_size, availability_zone, nics):
LOG.debug(_("begin _create_server_volume_heat for id: %s") % self.id)
try:
client = create_heat_client(self.context)
ifaces, ports = self._build_heat_nics(nics)
template_obj = template.load_heat_template(datastore_manager)
heat_template_unicode = template_obj.render(
volume_support=CONF.trove_volume_support)
volume_support=CONF.trove_volume_support,
ifaces=ifaces, ports=ports)
try:
heat_template = heat_template_unicode.encode('utf-8')
except UnicodeEncodeError:
@ -422,7 +427,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
def _create_server_volume_individually(self, flavor_id, image_id,
security_groups, datastore_manager,
volume_size,
availability_zone):
availability_zone, nics):
LOG.debug(_("begin _create_server_volume_individually for id: %s") %
self.id)
server = None
@ -432,7 +437,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
server = self._create_server(flavor_id, image_id, security_groups,
datastore_manager,
block_device_mapping,
availability_zone)
availability_zone, nics)
server_id = server.id
# Save server ID.
self.update_db(compute_instance_id=server_id)
@ -522,7 +527,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
def _create_server(self, flavor_id, image_id, security_groups,
datastore_manager, block_device_mapping,
availability_zone):
availability_zone, nics):
files = {"/etc/guest_info": ("[DEFAULT]\nguest_id=%s\n"
"datastore_manager=%s\n"
"tenant_id=%s\n" %
@ -542,7 +547,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
server = self.nova_client.servers.create(
name, image_id, flavor_id, files=files, userdata=userdata,
security_groups=security_groups, block_device_mapping=bdmap,
availability_zone=availability_zone)
availability_zone=availability_zone, nics=nics)
LOG.debug(_("Created new compute instance %(server_id)s "
"for id: %(id)s") %
{'server_id': server.id, 'id': self.id})
@ -616,6 +621,27 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
)
return [security_group["name"]]
def _build_heat_nics(self, nics):
ifaces = []
ports = []
if nics:
for idx, nic in enumerate(nics):
iface_id = nic.get('port-id')
if iface_id:
ifaces.append(iface_id)
continue
net_id = nic.get('net-id')
if net_id:
port = {}
port['name'] = "Port%s" % idx
port['net_id'] = net_id
fixed_ip = nic.get('v4-fixed-ip')
if fixed_ip:
port['fixed_ip'] = fixed_ip
ports.append(port)
ifaces.append("{Ref: Port%s}" % idx)
return ifaces, ports
class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin):
"""

View File

@ -18,6 +18,16 @@ Parameters:
TenantId:
Type: String
Resources:
{% for port in ports %}
{{ port.name }}:
Type: OS::Neutron::Port
Properties:
network_id: "{{ port.net_id }}"
security_groups: [{Ref: MySqlDbaasSG}]
{% if port.fixed_ip %}
fixed_ips: [{"ip_address": "{{ port.fixed_ip }}"}]
{% endif %}
{% endfor %}
BaseInstance:
Type: AWS::EC2::Instance
Metadata:
@ -38,7 +48,11 @@ Resources:
ImageId: {Ref: ImageId}
InstanceType: {Ref: Flavor}
AvailabilityZone: {Ref: AvailabilityZone}
SecurityGroups : [{Ref: MySqlDbaasSG}]
{% if ifaces %}
NetworkInterfaces: [{{ ifaces|join(', ') }}]
{% else %}
SecurityGroups: [{Ref: MySqlDbaasSG}]
{% endif %}
UserData:
Fn::Base64:
Fn::Join:

View File

@ -387,6 +387,15 @@ class CreateInstance(object):
None, databases, availability_zone="NOOP")
assert_equal(400, dbaas.last_http_code)
@test(enabled=not FAKE)
def test_create_with_bad_nics(self):
instance_name = "instance-failure-with-bad-nics"
databases = []
assert_raises(exceptions.BadRequest, dbaas.instances.create,
instance_name, instance_info.dbaas_flavor_href,
None, databases, nics="BAD")
assert_equal(400, dbaas.last_http_code)
@test(enabled=VOLUME_SUPPORT)
def test_create_failure_with_empty_volume(self):
instance_name = "instance-failure-with-no-volume-size"

View File

@ -260,7 +260,7 @@ class FakeServers(object):
def create(self, name, image_id, flavor_ref, files=None, userdata=None,
block_device_mapping=None, volume=None, security_groups=None,
availability_zone=None):
availability_zone=None, nics=None):
id = "FAKE_%s" % uuid.uuid4()
if volume:
volume = self.volumes.create(volume['size'], volume['name'],

View File

@ -48,7 +48,8 @@ class fake_Server:
class fake_ServerManager:
def create(self, name, image_id, flavor_id, files, userdata,
security_groups, block_device_mapping, availability_zone=None):
security_groups, block_device_mapping, availability_zone=None,
nics=None):
server = fake_Server()
server.id = "server_id"
server.name = name
@ -59,6 +60,7 @@ class fake_ServerManager:
server.security_groups = security_groups
server.block_device_mapping = block_device_mapping
server.availability_zone = availability_zone
server.nics = nics
return server
@ -180,33 +182,33 @@ class FreshInstanceTasksTest(testtools.TestCase):
when(taskmanager_models.CONF).get("cloudinit_location").thenReturn(
cloudinit_location)
server = self.freshinstancetasks._create_server(
None, None, None, datastore_manager, None, None)
None, None, None, datastore_manager, None, None, None)
self.assertEqual(server.userdata, self.userdata)
def test_create_instance_guestconfig(self):
when(taskmanager_models.CONF).get("guest_config").thenReturn(
self.guestconfig)
server = self.freshinstancetasks._create_server(
None, None, None, "test", None, None)
None, None, None, "test", None, None, None)
self.assertTrue('/etc/trove-guestagent.conf' in server.files)
self.assertEqual(server.files['/etc/trove-guestagent.conf'],
self.guestconfig_content)
def test_create_instance_with_az_kwarg(self):
server = self.freshinstancetasks._create_server(
None, None, None, None, None, availability_zone='nova')
None, None, None, None, None, availability_zone='nova', nics=None)
self.assertIsNotNone(server)
def test_create_instance_with_az(self):
server = self.freshinstancetasks._create_server(
None, None, None, None, None, 'nova')
None, None, None, None, None, 'nova', None)
self.assertIsNotNone(server)
def test_create_instance_with_az_none(self):
server = self.freshinstancetasks._create_server(
None, None, None, None, None, None)
None, None, None, None, None, None, None)
self.assertIsNotNone(server)