bug 793: fix detection of database not completely inited
[osm/RO.git] / osm_ro / vimconn_aws.py
index f0eebb6..bcd8cbc 100644 (file)
@@ -78,7 +78,7 @@ class vimconnector(vimconn.vimconnector):
         if 'region_name' in config:
             self.region = config.get('region_name')
         else:
         if 'region_name' in config:
             self.region = config.get('region_name')
         else:
-            raise vimconn.vimconnNotFoundException("AWS region_name is not specified at config")
+            raise vimconn.vimconnException("AWS region_name is not specified at config")
 
         self.vpc_data = {}
         self.subnet_data = {}
 
         self.vpc_data = {}
         self.subnet_data = {}
@@ -109,8 +109,11 @@ class vimconnector(vimconn.vimconnector):
             flavor_data = config.get('flavor_info')
             if isinstance(flavor_data, str):
                 try:
             flavor_data = config.get('flavor_info')
             if isinstance(flavor_data, str):
                 try:
-                    with open(flavor_data[1:], 'r') as stream:
-                        self.flavor_info = yaml.load(stream)
+                    if flavor_data[0] == "@":  # read from a file
+                        with open(flavor_data[1:], 'r') as stream:
+                            self.flavor_info = yaml.load(stream)
+                    else:
+                        self.flavor_info = yaml.load(flavor_data)
                 except yaml.YAMLError as e:
                     self.flavor_info = None
                     raise vimconn.vimconnException("Bad format at file '{}': {}".format(flavor_data[1:], e))
                 except yaml.YAMLError as e:
                     self.flavor_info = None
                     raise vimconn.vimconnException("Bad format at file '{}': {}".format(flavor_data[1:], e))
@@ -296,11 +299,16 @@ class vimconnector(vimconn.vimconnector):
                     'count': number of IPs to grant.
             'shared': if this network can be seen/use by other tenants/organization
             'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
                     'count': number of IPs to grant.
             'shared': if this network can be seen/use by other tenants/organization
             'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
-        Returns the network identifier on success or raises and exception on failure
+        Returns a tuple with the network identifier and created_items, or raises an exception on error
+            created_items can be None or a dictionary where this method can include key-values that will be passed to
+            the method delete_network. Can be used to store created segments, created l2gw connections, etc.
+            Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
+            as not present.
         """
 
         self.logger.debug("Adding a subnet to VPC")
         try:
         """
 
         self.logger.debug("Adding a subnet to VPC")
         try:
+            created_items = {}
             self._reload_connection()
             subnet = None
             vpc_id = self.vpc_id
             self._reload_connection()
             subnet = None
             vpc_id = self.vpc_id
@@ -311,7 +319,7 @@ class vimconnector(vimconn.vimconnector):
                 subnet_list = self.subnet_sizes(len(self.get_availability_zones_list()), vpc['cidr_block'])
                 cidr_block = list(set(subnet_list) - set(self.get_network_details({'tenant_id': vpc['id']}, detail='cidr_block')))[0]
             subnet = self.conn_vpc.create_subnet(vpc_id, cidr_block)
                 subnet_list = self.subnet_sizes(len(self.get_availability_zones_list()), vpc['cidr_block'])
                 cidr_block = list(set(subnet_list) - set(self.get_network_details({'tenant_id': vpc['id']}, detail='cidr_block')))[0]
             subnet = self.conn_vpc.create_subnet(vpc_id, cidr_block)
-            return subnet.id
+            return subnet.id, created_items
         except Exception as e:
             self.format_vimconn_exception(e)
 
         except Exception as e:
             self.format_vimconn_exception(e)
 
@@ -351,12 +359,12 @@ class vimconnector(vimconn.vimconnector):
             if filter_dict != {}:
                 if 'tenant_id' in filter_dict:
                     tfilters['vpcId'] = filter_dict['tenant_id']
             if filter_dict != {}:
                 if 'tenant_id' in filter_dict:
                     tfilters['vpcId'] = filter_dict['tenant_id']
-            subnets = self.conn_vpc.get_all_subnets(subnet_ids=filter_dict.get('id', None), filters=tfilters)
+            subnets = self.conn_vpc.get_all_subnets(subnet_ids=filter_dict.get('name', None), filters=tfilters)
             net_list = []
             for net in subnets:
                 net_list.append(
                     {'id': str(net.id), 'name': str(net.id), 'status': str(net.state), 'vpc_id': str(net.vpc_id),
             net_list = []
             for net in subnets:
                 net_list.append(
                     {'id': str(net.id), 'name': str(net.id), 'status': str(net.state), 'vpc_id': str(net.vpc_id),
-                     'cidr_block': str(net.cidr_block)})
+                     'cidr_block': str(net.cidr_block), 'type': 'bridge'})
             return net_list
         except Exception as e:
             self.format_vimconn_exception(e)
             return net_list
         except Exception as e:
             self.format_vimconn_exception(e)
@@ -381,8 +389,11 @@ class vimconnector(vimconn.vimconnector):
         except Exception as e:
             self.format_vimconn_exception(e)
 
         except Exception as e:
             self.format_vimconn_exception(e)
 
-    def delete_network(self, net_id):
-        """Deletes a tenant network from VIM
+    def delete_network(self, net_id, created_items=None):
+        """
+        Removes a tenant network from VIM and its associated elements
+        :param net_id: VIM identifier of the network, provided by method new_network
+        :param created_items: dictionary with extra items to be deleted. provided by method new_network
         Returns the network identifier or raises an exception upon error or when network is not found
         """
 
         Returns the network identifier or raises an exception upon error or when network is not found
         """
 
@@ -590,7 +601,7 @@ class vimconnector(vimconn.vimconnector):
             self.format_vimconn_exception(e)
 
     def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None,
             self.format_vimconn_exception(e)
 
     def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None,
-                       disk_list=None):
+                       disk_list=None, availability_zone_index=None, availability_zone_list=None):
         """Create a new VM/instance in AWS
         Params: name
                 decription
         """Create a new VM/instance in AWS
         Params: name
                 decription
@@ -601,13 +612,13 @@ class vimconnector(vimconn.vimconnector):
                     name
                     net_id - subnet_id from AWS
                     vpci - (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
                     name
                     net_id - subnet_id from AWS
                     vpci - (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
-                    model: (optional and only have sense for type==virtual) interface model: virtio, e2000, ...
+                    model: (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
                     mac_address: (optional) mac address to assign to this interface
                     type: (mandatory) can be one of:
                         virtual, in this case always connected to a network of type 'net_type=bridge'
                     mac_address: (optional) mac address to assign to this interface
                     type: (mandatory) can be one of:
                         virtual, in this case always connected to a network of type 'net_type=bridge'
-                        PF - (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
-                               can created unconnected
-                        VF - (SRIOV with VLAN tag): same as PF for network connectivity.
+                        'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
+                           can created unconnected
+                        'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
                         VFnotShared - (SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
                             are allocated on the same physical NIC
                     bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
                         VFnotShared - (SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
                             are allocated on the same physical NIC
                     bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
@@ -634,59 +645,18 @@ class vimconnector(vimconn.vimconnector):
                 disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
                     image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
                     size': (mandatory) string with the size of the disk in GB
                 disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
                     image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
                     size': (mandatory) string with the size of the disk in GB
-        Returns: instance identifier or raises an exception on error
+        Returns a tuple with the instance identifier and created_items or raises an exception on error
+            created_items can be None or a dictionary where this method can include key-values that will be passed to
+            the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
+            Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
+            as not present.
         """
 
         self.logger.debug("Creating a new VM instance")
         try:
             self._reload_connection()
             instance = None
         """
 
         self.logger.debug("Creating a new VM instance")
         try:
             self._reload_connection()
             instance = None
-            userdata = None
-            if isinstance(cloud_config, dict):
-                if cloud_config.get("user-data"):
-                    userdata = cloud_config["user-data"]
-                if cloud_config.get("config-files") or cloud_config.get("users") or cloud_config.get("key-pairs"):
-                    if userdata:
-                        raise vimconn.vimconnConflictException(
-                            "Cloud-config cannot contain both 'userdata' and 'config-files'/'users'/'key-pairs'")
-                    userdata_dict = {}
-                    # default user
-                    if cloud_config.get("key-pairs"):
-                        userdata_dict["ssh-authorized-keys"] = cloud_config["key-pairs"]
-                        userdata_dict["users"] = [{"default": None, "ssh-authorized-keys": cloud_config["key-pairs"]}]
-                    if cloud_config.get("users"):
-                        if "users" not in userdata_dict:
-                            userdata_dict["users"] = ["default"]
-                        for user in cloud_config["users"]:
-                            user_info = {
-                                "name": user["name"],
-                                "sudo": "ALL = (ALL)NOPASSWD:ALL"
-                            }
-                            if "user-info" in user:
-                                user_info["gecos"] = user["user-info"]
-                            if user.get("key-pairs"):
-                                user_info["ssh-authorized-keys"] = user["key-pairs"]
-                            userdata_dict["users"].append(user_info)
-
-                    if cloud_config.get("config-files"):
-                        userdata_dict["write_files"] = []
-                        for file in cloud_config["config-files"]:
-                            file_info = {
-                                "path": file["dest"],
-                                "content": file["content"]
-                            }
-                            if file.get("encoding"):
-                                file_info["encoding"] = file["encoding"]
-                            if file.get("permissions"):
-                                file_info["permissions"] = file["permissions"]
-                            if file.get("owner"):
-                                file_info["owner"] = file["owner"]
-                            userdata_dict["write_files"].append(file_info)
-                    userdata = "#cloud-config\n"
-                    userdata += yaml.safe_dump(userdata_dict, indent=4, default_flow_style=False)
-                self.logger.debug("userdata: %s", userdata)
-            elif isinstance(cloud_config, str):
-                userdata = cloud_config
+            _, userdata = self._create_user_data(cloud_config)
 
             if not net_list:
                 reservation = self.conn.run_instances(
 
             if not net_list:
                 reservation = self.conn.run_instances(
@@ -696,9 +666,7 @@ class vimconnector(vimconn.vimconnector):
                     security_groups=self.security_groups,
                     user_data=userdata
                 )
                     security_groups=self.security_groups,
                     user_data=userdata
                 )
-                instance = reservation.instances[0]
             else:
             else:
-                net_list = [net_list[0]]
                 for index, subnet in enumerate(net_list):
                     net_intr = boto.ec2.networkinterface.NetworkInterfaceSpecification(subnet_id=subnet.get('net_id'),
                                                                                        groups=None,
                 for index, subnet in enumerate(net_list):
                     net_intr = boto.ec2.networkinterface.NetworkInterfaceSpecification(subnet_id=subnet.get('net_id'),
                                                                                        groups=None,
@@ -717,7 +685,6 @@ class vimconnector(vimconn.vimconnector):
                             network_interfaces=boto.ec2.networkinterface.NetworkInterfaceCollection(net_intr),
                             user_data=userdata
                         )
                             network_interfaces=boto.ec2.networkinterface.NetworkInterfaceCollection(net_intr),
                             user_data=userdata
                         )
-                        instance = reservation.instances[0]
                     else:
                         while True:
                             try:
                     else:
                         while True:
                             try:
@@ -727,7 +694,10 @@ class vimconnector(vimconn.vimconnector):
                                 break
                             except:
                                 time.sleep(10)
                                 break
                             except:
                                 time.sleep(10)
-            return instance.id
+                    net_list[index]['vim_id'] = reservation.instances[0].interfaces[index].id
+
+            instance = reservation.instances[0]
+            return instance.id, None
         except Exception as e:
             self.format_vimconn_exception(e)
 
         except Exception as e:
             self.format_vimconn_exception(e)
 
@@ -741,7 +711,7 @@ class vimconnector(vimconn.vimconnector):
         except Exception as e:
             self.format_vimconn_exception(e)
 
         except Exception as e:
             self.format_vimconn_exception(e)
 
-    def delete_vminstance(self, vm_id):
+    def delete_vminstance(self, vm_id, created_items=None):
         """Removes a VM instance from VIM
         Returns the instance identifier"""
 
         """Removes a VM instance from VIM
         Returns the instance identifier"""
 
@@ -796,7 +766,10 @@ class vimconnector(vimconn.vimconnector):
                         interface_dict['vim_interface_id'] = interface.id
                         interface_dict['vim_net_id'] = interface.subnet_id
                         interface_dict['mac_address'] = interface.mac_address
                         interface_dict['vim_interface_id'] = interface.id
                         interface_dict['vim_net_id'] = interface.subnet_id
                         interface_dict['mac_address'] = interface.mac_address
-                        interface_dict['ip_address'] = interface.private_ip_address
+                        if hasattr(interface, 'publicIp') and interface.publicIp != None:
+                            interface_dict['ip_address'] = interface.publicIp + ";" + interface.private_ip_address
+                        else:
+                            interface_dict['ip_address'] = interface.private_ip_address
                         instance_dict['interfaces'].append(interface_dict)
                 except Exception as e:
                     self.logger.error("Exception getting vm status: %s", str(e), exc_info=True)
                         instance_dict['interfaces'].append(interface_dict)
                 except Exception as e:
                     self.logger.error("Exception getting vm status: %s", str(e), exc_info=True)
@@ -814,7 +787,7 @@ class vimconnector(vimconn.vimconnector):
             self.logger.error("Exception getting vm status: %s", str(e), exc_info=True)
             self.format_vimconn_exception(e)
 
             self.logger.error("Exception getting vm status: %s", str(e), exc_info=True)
             self.format_vimconn_exception(e)
 
-    def action_vminstance(self, vm_id, action_dict):
+    def action_vminstance(self, vm_id, action_dict, created_items={}):
         """Send and action over a VM instance from VIM
         Returns the vm_id if the action was successfully sent to the VIM"""
 
         """Send and action over a VM instance from VIM
         Returns the vm_id if the action was successfully sent to the VIM"""
 
@@ -829,6 +802,6 @@ class vimconnector(vimconn.vimconnector):
                 self.conn.terminate_instances(vm_id)
             elif "reboot" in action_dict:
                 self.conn.reboot_instances(vm_id)
                 self.conn.terminate_instances(vm_id)
             elif "reboot" in action_dict:
                 self.conn.reboot_instances(vm_id)
-            return vm_id
+            return None
         except Exception as e:
             self.format_vimconn_exception(e)
         except Exception as e:
             self.format_vimconn_exception(e)