net['type']='data'
else:
net['type']='bridge'
-
-
-
+
def _format_exception(self, exception):
'''Transform a keystone, nova, neutron exception into a vimconn exception'''
if isinstance(exception, (HTTPException, gl1Exceptions.HTTPException, gl1Exceptions.CommunicationError,
raise vimconn.vimconnNotFoundException(type(exception).__name__ + ": " + str(exception))
elif isinstance(exception, nvExceptions.Conflict):
raise vimconn.vimconnConflictException(type(exception).__name__ + ": " + str(exception))
+ elif isinstance(exception, vimconn.vimconnException):
+ raise
else: # ()
+ self.logger.error("General Exception " + str(exception), exc_info=True)
raise vimconn.vimconnConnectionException(type(exception).__name__ + ": " + str(exception))
def get_tenant_list(self, filter_dict={}):
ip_profile['subnet_address'] = "192.168.{}.0/24".format(subnet_rand)
if 'ip_version' not in ip_profile:
ip_profile['ip_version'] = "IPv4"
- subnet={"name":net_name+"-subnet",
+ subnet = {"name":net_name+"-subnet",
"network_id": new_net["network"]["id"],
"ip_version": 4 if ip_profile['ip_version']=="IPv4" else 6,
"cidr": ip_profile['subnet_address']
}
- if 'gateway_address' in ip_profile:
- subnet['gateway_ip'] = ip_profile['gateway_address']
+ # Gateway should be set to None if not needed. Otherwise openstack assigns one by default
+ subnet['gateway_ip'] = ip_profile.get('gateway_address')
if ip_profile.get('dns_address'):
subnet['dns_nameservers'] = ip_profile['dns_address'].split(";")
if 'dhcp_enabled' in ip_profile:
subnet['enable_dhcp'] = False if ip_profile['dhcp_enabled']=="false" else True
if 'dhcp_start_address' in ip_profile:
- subnet['allocation_pools']=[]
+ subnet['allocation_pools'] = []
subnet['allocation_pools'].append(dict())
subnet['allocation_pools'][0]['start'] = ip_profile['dhcp_start_address']
if 'dhcp_count' in ip_profile:
except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError, ConnectionError) as e:
self._format_exception(e)
+ def __wait_for_vm(self, vm_id, status):
+ """wait until vm is in the desired status and return True.
+ If the VM gets in ERROR status, return false.
+ If the timeout is reached generate an exception"""
+ elapsed_time = 0
+ while elapsed_time < server_timeout:
+ vm_status = self.nova.servers.get(vm_id).status
+ if vm_status == status:
+ return True
+ if vm_status == 'ERROR':
+ return False
+ time.sleep(1)
+ elapsed_time += 1
+
+ # if we exceeded the timeout rollback
+ if elapsed_time >= server_timeout:
+ raise vimconn.vimconnException('Timeout waiting for instance ' + vm_id + ' to get ' + status,
+ http_code=vimconn.HTTP_Request_Timeout)
+
def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None,disk_list=None):
'''Adds a VM instance to VIM
Params:
'''
self.logger.debug("new_vminstance input: image='%s' flavor='%s' nics='%s'",image_id, flavor_id,str(net_list))
try:
+ server = None
metadata={}
net_list_vim=[]
- external_network=[] #list of external networks to be connected to instance, later on used to create floating_ip
+ external_network=[] # list of external networks to be connected to instance, later on used to create floating_ip
+ no_secured_ports = [] # List of port-is with port-security disabled
self._reload_connection()
- metadata_vpci={} #For a specific neutron plugin
+ metadata_vpci={} # For a specific neutron plugin
+ block_device_mapping = None
for net in net_list:
if not net.get("net_id"): #skip non connected iface
continue
metadata_vpci["VF"]=[]
metadata_vpci["VF"].append([ net["vpci"], "" ])
port_dict["binding:vnic_type"]="direct"
- else: #For PT
+ else: # For PT
if "vpci" in net:
if "PF" not in metadata_vpci:
metadata_vpci["PF"]=[]
port_dict["name"]=name
if net.get("mac_address"):
port_dict["mac_address"]=net["mac_address"]
- if net.get("port_security") == False:
- port_dict["port_security_enabled"]=net["port_security"]
new_port = self.neutron.create_port({"port": port_dict })
net["mac_adress"] = new_port["port"]["mac_address"]
net["vim_id"] = new_port["port"]["id"]
- net["ip"] = new_port["port"].get("fixed_ips", [{}])[0].get("ip_address")
+ # if try to use a network without subnetwork, it will return a emtpy list
+ fixed_ips = new_port["port"].get("fixed_ips")
+ if fixed_ips:
+ net["ip"] = fixed_ips[0].get("ip_address")
+ else:
+ net["ip"] = None
net_list_vim.append({"port-id": new_port["port"]["id"]})
if net.get('floating_ip', False):
net['exit_on_floating_ip_error'] = False
external_network.append(net)
+ # If port security is disabled when the port has not yet been attached to the VM, then all vm traffic is dropped.
+ # As a workaround we wait until the VM is active and then disable the port-security
+ if net.get("port_security") == False:
+ no_secured_ports.append(new_port["port"]["id"])
+
if metadata_vpci:
metadata = {"pci_assignement": json.dumps(metadata_vpci)}
if len(metadata["pci_assignement"]) >255:
userdata = cloud_config
#Create additional volumes in case these are present in disk_list
- block_device_mapping = None
base_disk_index = ord('b')
if disk_list != None:
- block_device_mapping = dict()
+ block_device_mapping = {}
for disk in disk_list:
if 'image_id' in disk:
volume = self.cinder.volumes.create(size = disk['size'],name = name + '_vd' +
availability_zone=self.config.get('availability_zone'),
key_name=self.config.get('keypair'),
userdata=userdata,
- config_drive = config_drive,
- block_device_mapping = block_device_mapping
+ config_drive=config_drive,
+ block_device_mapping=block_device_mapping
) # , description=description)
+
+ # Previously mentioned workaround to wait until the VM is active and then disable the port-security
+ if no_secured_ports:
+ self.__wait_for_vm(server.id, 'ACTIVE')
+
+ for port_id in no_secured_ports:
+ try:
+ self.neutron.update_port(port_id, {"port": {"port_security_enabled": False, "security_groups": None} })
+
+ except Exception as e:
+ self.logger.error("It was not possible to disable port security for port {}".format(port_id))
+ self.delete_vminstance(server.id)
+ raise
+
#print "DONE :-)", server
pool_id = None
floating_ips = self.neutron.list_floatingips().get("floatingips", ())
- for floating_network in external_network:
- try:
- # wait until vm is active
- elapsed_time = 0
- while elapsed_time < server_timeout:
- status = self.nova.servers.get(server.id).status
- if status == 'ACTIVE':
- break
- time.sleep(1)
- elapsed_time += 1
- #if we exceeded the timeout rollback
- if elapsed_time >= server_timeout:
- raise vimconn.vimconnException('Timeout creating instance ' + name,
- http_code=vimconn.HTTP_Request_Timeout)
+ if external_network:
+ self.__wait_for_vm(server.id, 'ACTIVE')
+ for floating_network in external_network:
+ try:
assigned = False
while(assigned == False):
if floating_ips:
if not floating_network['exit_on_floating_ip_error']:
self.logger.warn("Cannot create floating_ip. %s", str(e))
continue
- self.delete_vminstance(server.id)
raise
return server.id
# except nvExceptions.NotFound as e:
# error_value=-vimconn.HTTP_Not_Found
# error_text= "vm instance %s not found" % vm_id
- except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError) as e:
+# except TypeError as e:
+# raise vimconn.vimconnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request)
+
+ except Exception as e:
# delete the volumes we just created
- if block_device_mapping != None:
+ if block_device_mapping:
for volume_id in block_device_mapping.itervalues():
self.cinder.volumes.delete(volume_id)
- # delete ports we just created
- for net_item in net_list_vim:
- if 'port-id' in net_item:
- self.neutron.delete_port(net_item['port-id'])
+ # Delete the VM
+ if server != None:
+ self.delete_vminstance(server.id)
+ else:
+ # delete ports we just created
+ for net_item in net_list_vim:
+ if 'port-id' in net_item:
+ self.neutron.delete_port(net_item['port-id'])
+
self._format_exception(e)
- except TypeError as e:
- raise vimconn.vimconnException(type(e).__name__ + ": "+ str(e), http_code=vimconn.HTTP_Bad_Request)
def get_vminstance(self,vm_id):
'''Returns the VM instance information from VIM'''