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 = {}
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))
'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:
+ created_items = {}
self._reload_connection()
subnet = None
vpc_id = self.vpc_id
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)
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),
- '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)
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
"""
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
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'
- 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
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
- 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(
security_groups=self.security_groups,
user_data=userdata
)
- instance = reservation.instances[0]
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,
network_interfaces=boto.ec2.networkinterface.NetworkInterfaceCollection(net_intr),
user_data=userdata
)
- instance = reservation.instances[0]
else:
while True:
try:
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)
- 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"""
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)
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"""
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)