Merge "Add Neutron support"
This commit is contained in:
commit
312244d451
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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'],
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue