示例#1
0
class VMHandler():
    def __init__(self):
        self.db = ProviderDb()
        self.SOUTHBOUND_DIRECTORY = 'overlay_south'

    def create_vm(self, args):
        customer_id = args['customerId']
        vpc_id = args['vpcId']
        subnet_id = args['subnetId']
        vm_name = args['vmName']

        # verify customer id
        if (self.db.get_customer_by_id(customer_id) == None):
            return {
                "message":
                "No customer found with id '{0}'".format(customer_id),
                "success": False
            }

        # verify vpc id
        vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
        if (vpc == None):
            return {
                "message":
                "No vpc found with id '{0}' for customer '{1}'".format(
                    vpc_id, customer_id),
                "success":
                False
            }

        # verify subnet id
        subnet = self.db.get_subnet_by_id(subnet_id, vpc_id)
        if (subnet == None):
            return {
                "message":
                "failed to get subnet id '{0}' for vpc id '{1}'".format(
                    subnet_id, vpc_id),
                "success":
                False
            }

        # check db to see if VM exists...
        if (self.db.get_vm(vm_name, subnet_id) != None):
            return {
                "message":
                "vm '{0}' already exists in subnet '{1}'".format(
                    vm_name, subnet_id),
                "success":
                False
            }

        # ...NO VM exists at this point...

        # create MAC address
        mac_addr = self.generate_mac_addr()

        # create IP address
        do_not_use_ip_list = self.db.get_all_vm_ip_addrs(subnet_id)
        ip_addr = self.generate_ip_addr(subnet.ipAddress, do_not_use_ip_list)

        if ip_addr == None:
            return {
                "message":
                "No more ip addresses available for subnet '{0}' (id: '{1}') in vpc '{2}'"
                .format(subnet.ipAddress, subnet.subnetId, vpc.vpcName),
                "success":
                False
            }

        # create unique vm name
        vm_id = self.db.get_next_vm_id()
        if vm_id < 0:
            return {
                "message":
                "A SQL error occured in creating VM '{0}'".format(vm_name),
                "success":
                False
            }
        unique_vm_name = "{0}_{1}".format(vm_name, str(vm_id))

        # create vm physically
        phy_result = self.create_physically(vm_id, unique_vm_name, mac_addr,
                                            ip_addr, subnet_id, vpc_id,
                                            vpc.host)

        # save in db if successful
        if phy_result:
            return self.create_in_db(unique_vm_name, mac_addr, ip_addr,
                                     subnet_id, vpc_id)
        else:
            return {
                "message":
                "Unable to physically create vm '{0}' for subnet {1}".format(
                    vm_name, subnet_id),
                "success":
                False
            }

    def create_physically(self, vmId, vmName, macAddr, ipAddr, subnetId, vpcId,
                          host):
        # # TODO: Fix this!
        # return True

        args = {
            "guests": [{
                "name": vmName,
                "subnet_id": subnetId,
                "vpc_id": vpcId,
                "vm_id": vmId,
                "mac_address": macAddr
            }]
        }
        commands = [
            "sudo", "ansible-playbook", "create-vms.yml", "-i", "hosts.ini",
            "-e",
            json.dumps(args), "-l {0}".format(host.lower())
        ]
        p = subprocess.Popen(commands, cwd=self.SOUTHBOUND_DIRECTORY)
        p.wait()

        if p.returncode != 0:
            print(
                "\r\nUnable to run ansible 'create-vms.yml' in vm_handler.create_physically\r\n"
            )
            return False
        else:
            return True

    def generate_mac_addr(self) -> str:
        mac = [
            0x08, 0x00, 0x22,
            random.randint(0x00, 0x7f),
            random.randint(0x00, 0xff),
            random.randint(0x00, 0xff)
        ]

        return ':'.join(map(lambda x: "%02x" % x, mac))

    def generate_ip_addr(self, subnet_ip: str,
                         do_not_use_ip_list: list) -> str:
        # subnet_ip ex: "192.168.2.0/28"
        ip_range = ipaddress.IPv4Network(subnet_ip)
        network_addr = str(ip_range.network_address)
        broadcast_addr = str(ip_range.broadcast_address)
        the_ip_addr = None

        for ip in ip_range.hosts():
            ip_str = str(ip)

            if ip_str == network_addr:
                print("Network IP '{0}' cannot be used".format(ip_str))
                continue

            # do not return an already used IP!
            if ip_str in do_not_use_ip_list:
                print("IP '{0}' is already used".format(ip_str))
                continue

            if ip_str == broadcast_addr:
                print("Broadcast IP '{0}' cannot be used".format(ip_str))
                continue

            print("IP to be assigned to vm is: '{0}'\r\n".format(ip_str))
            return ip_str

    def create_in_db(self, vm_name, mac_addr, ip_addr, subnet_id, vpc_id):
        vm_id_str = self.db.create_vm(vm_name, mac_addr, ip_addr, subnet_id,
                                      vpc_id)
        if (vm_id_str != None):
            return {
                "message":
                "Vm '{0}' (ID '{1}', ip '{2}') created in subnet '{3}'.".
                format(vm_name, vm_id_str, ip_addr, subnet_id),
                "success":
                True
            }
        else:
            return {
                "message":
                "failed to add in db the vm '{0}' (ip '{1}') in subnet '{2}'".
                format(vm_name, ip_addr, subnet_id),
                "success":
                False
            }

    def delete_vm(self, args):
        customer_name = args['customerName']
        vmNames = args['vmNames']  # a list

        output = {}
        output["notice"] = []
        output["success"] = False

        for vm_str_obj in vmNames:
            # convert str to dict
            vm_str_obj = vm_str_obj.replace("\'", "\"")
            vm = json.loads(vm_str_obj)
            print(vm)

            host = vm["host"]
            vm_name = vm["vmName"]
            vm_ip = vm["vmIp"]
            subnet_ip = vm["subnetIp"]
            vpc_name = vm["vpcName"]

            # get vpc
            vpc = self.db.get_vpc(vpc_name, customer_name, host)
            if vpc == None:
                output["notice"].append({
                    "message":
                    "No vpc found with name '{0}' for customer '{1}' in host '{2}'"
                    .format(vpc_name, customer_name, host),
                    "success":
                    False
                })
                continue
            else:
                vpc_id = vpc.vpcId

            # get subnet
            subnet = self.db.get_subnet(subnet_ip, vpc_id)
            if subnet == None:
                output["notice"].append({
                    "message":
                    "No subnet '{0}' found in vpc '{1}' (vpc id={2}) in host '{3}'"
                    .format(subnet_ip, vpc.vpcName, vpc.vpcId, host),
                    "success":
                    False
                })
                continue
            else:
                subnet_id = subnet.subnetId

            vm = self.db.get_vm(vm_name, subnet.subnetId)
            if (vm == None):
                output["notice"].append({
                    "message":
                    "No VM '{0}' found in subnet '{1}' (subnet id={2}) in vpc '{3}'"
                    .format(vm_name, subnet_ip, subnet.subnetId, vpc.vpcName),
                    "success":
                    False
                })
                continue
            else:
                vm_id = vm.vmId

            phy_result = self.delete_physically(host, vm_name, vm_ip)

            if phy_result:
                db_result = self.delete_in_db(vm_id, vm_name, subnet_ip,
                                              vpc_name)

                if db_result:
                    output["notice"].append({
                        "message":
                        "Successfully deleted vm {0} in subnet '{1}' (subnet id={2}) in vpc '{3}'"
                        .format(vm_name, subnet_ip, subnet.subnetId,
                                vpc.vpcName),
                        "dbMessage":
                        db_result,
                        "success":
                        True
                    })
                    output["success"] = True

                else:
                    output["notice"].append({
                        "message":
                        "Failed to delete vm {0} in subnet '{1}' (subnet id={2}) in vpc '{3}'"
                        .format(vm_name, subnet_ip, subnet.subnetId,
                                vpc.vpcName),
                        "dbMessage":
                        db_result,
                        "success":
                        False
                    })
                    output["success"] = False

            else:
                output["notice"].append({
                    "message":
                    "Failed to physically delete VM {0} with ip {1} in host {2}"
                    .format(vm_name, vm_ip, host),
                    "success":
                    False
                })
                output["success"] = False

        return output

    def delete_physically(self, host, vm_name, vm_ip):
        return True  # TODO: Fix this!

    def delete_in_db(self, vm_id, vm_name, subnet_ip, vpc_name):
        delete_ok = self.db.delete_vm(vm_id)
        if (delete_ok):
            results = {
                "message":
                "vm '{0}' is deleted from subnet '{1}' in vpc {2}".format(
                    vm_name, subnet_ip, vpc_name),
                "success":
                True
            }
        else:
            results = {
                "message":
                "Failed to delete vm '{0}' from subnet '{1}' in vpc {2}".
                format(vm_name, subnet_ip, vpc_name),
                "success":
                False
            }

        return results
示例#2
0
class SubnetHandler:

    def __init__(self):
        self.db = ProviderDb()
        self.SOUTHBOUND_DIRECTORY = 'overlay_south'

    def get_all_subnets(self, args) -> list:
        customer_id = args["customerId"]

        vpc_id_list = self.db.get_all_vpcs(customer_id)
        ret_list = []

        for vpc_id in vpc_id_list:
            vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
            subnets = self.db.get_all_subnets(vpc_id)
            sub_list = []

            for subnet in subnets:
                s = {}
                s["subnetId"] = subnet.subnetId
                s["vpcId"] = subnet.vpcId
                s["ipAddress"] = subnet.ipAddress
                s["subnetName"] = subnet.subnetName

                sub_list.append(s)

            ret_list.append(
                {"vpcId": vpc_id, "vpcName": vpc.vpcName, "host": vpc.host, "subnets": sub_list})

        return {"message": ret_list, "success": True}

    def create_subnet(self, args):
        global bgp_vpc_map
        customer_id = args["customerId"]
        vpc_id = args["vpcId"]
        subnet_str = args["subnet"]

        if (self.db.get_customer_by_id(customer_id) == None):
            return {"message": "No customer found with id '{0}'".format(customer_id), "success": False}

        # get vpc
        vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
        if(vpc == None):
            return {"message": "No vpc found with id '{0}' for customer '{1}'".format(vpc_id, customer_id), "success": False}

        # convert str to dict
        subnet_str = subnet_str.replace("\'", "\"")
        subnet = json.loads(subnet_str)
        ip_address = subnet["ipAddress"]
        subnet_name = subnet["subnetName"]

        # verify valid ip NETWORK address
        ip_ok, ip_error = self.ensure_valid_ip_network(ip_address)
        if not ip_ok and ip_error == None:
            return {"message": "Invalid ip given! Fix this --> '{0}' ".format(ip_address), "success": False}
        if not ip_ok and ip_error != None:
            return {"message": "Invalid ip NETWORK address given! The network address is: '{0}'! Fix this --> '{1}' ".format(ip_error, ip_address), "success": False}

        # check db to see if subnet exists
        if(self.db.get_subnet(ip_address, vpc_id) != None):
            return {
                "message": "subnet '{0}' for vpc {1} (id '{2}') already exists".format(
                    ip_address, vpc.vpcName, vpc_id),
                "success": False
            }
        else:
            # save in db if successful
            if self.create_physically(ip_address, vpc_id, vpc.host, vpc.scaleFactor):
                subnetId = self.create_in_db(vpc_id, ip_address, subnet_name)
                # restart bgp service in the edges
                bgp_configurations = bgp_vpc_map[vpc_id]
                # for all configs, update it with new network and restart vpc
                for i in range(len(bgp_configurations)):
                    config = bgp_configurations[i]
                    config.autonomus_systems[0].add_network(ip_address)
                    filename = "edge-%s-%s.conf" % (vpc_id, i)
                    config.write_config_to(filename)
                
                # restart the edge
                for i in vpc.scaleFactor:
                    ns = "V%sE%s" % (vpc_id, i)
class SubnetHandler:

    def __init__(self):
        self.db = ProviderDb()
        self.SOUTHBOUND_DIRECTORY = 'overlay_south'

    def get_all_subnets(self, args) -> list:
        customer_id = args["customerId"]

        vpc_id_list = self.db.get_all_vpcs(customer_id)
        ret_list = []

        for vpc_id in vpc_id_list:
            vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
            subnets = self.db.get_all_subnets(vpc_id)
            sub_list = []

            for subnet in subnets:
                s = {}
                s["subnetId"] = subnet.subnetId
                s["vpcId"] = subnet.vpcId
                s["ipAddress"] = subnet.ipAddress
                s["subnetName"] = subnet.subnetName

                sub_list.append(s)

            ret_list.append(
                {"vpcId": vpc_id, "vpcName": vpc.vpcName, "host": vpc.host, "subnets": sub_list})

        return {"message": ret_list, "success": True}

    def create_subnet(self, args):
        customer_id = args["customerId"]
        vpc_id = args["vpcId"]
        subnet_str = args["subnet"]

        if (self.db.get_customer_by_id(customer_id) == None):
            return {"message": "No customer found with id '{0}'".format(customer_id), "success": False}

        # get vpc
        vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
        if(vpc == None):
            return {"message": "No vpc found with id '{0}' for customer '{1}'".format(vpc_id, customer_id), "success": False}

        # convert str to dict
        subnet_str = subnet_str.replace("\'", "\"")
        subnet = json.loads(subnet_str)
        ip_address = subnet["ipAddress"]
        subnet_name = subnet["subnetName"]

        # verify valid ip NETWORK address
        ip_ok, ip_error = self.ensure_valid_ip_network(ip_address)
        if not ip_ok and ip_error == None:
            return {"message": "Invalid ip given! Fix this --> '{0}' ".format(ip_address), "success": False}
        if not ip_ok and ip_error != None:
            return {"message": "Invalid ip NETWORK address given! The network address is: '{0}'! Fix this --> '{1}' ".format(ip_error, ip_address), "success": False}

        # check db to see if subnet exists
        if(self.db.get_subnet(ip_address, vpc_id) != None):
            return {
                "message": "subnet '{0}' for vpc {1} (id '{2}') already exists".format(
                    ip_address, vpc.vpcName, vpc_id),
                "success": False
            }
        else:
            # save in db if successful
            if self.create_physically(ip_address, vpc_id, vpc.host, vpc.scaleFactor):
                subnetId = self.create_in_db(vpc_id, ip_address, subnet_name)
                return {
                    "subnet_id":subnetId,
                    "message": "Successfully created a physical subnet '{0}'for vpc '{1}' in host '{2}'".format(ip_address, vpc_id, vpc.host),
                    #"dbMessage": db_result,
                    "success": True
                }
            else:
                return {
                    "message": "Unable to physically create subnet '{0}' for vpc {1} (id is {2})".format(ip_address, vpc.vpcName, vpc_id),
                    "success": False
                }

    def ensure_valid_ip_network(self, subnet_str):
        try:
            valid_ip_network = ipaddress.IPv4Interface(subnet_str).network
            print(valid_ip_network)
            print(subnet_str)
            if str(valid_ip_network) != subnet_str:
                return False, valid_ip_network
            else:
                return True, None
        except Exception as e:
            traceback.print_exception(type(e), e, e.__traceback__)
            return False, None

    def create_physically(self, ip_address, vpc_id, host, scaleFactor):
        result = False
        host = host.lower()

        subnet_id = self.db.get_next_subnet_id()
        if subnet_id < 0:
            return {"message": "A SQL error occured in creating subnet '{0}'".format(ip_address), "success": False}

        try:
            json_obj = {}
            json_obj["subnet_id"] = subnet_id
            json_obj["vpc_id"] = vpc_id
            json_obj["edge_count"] = scaleFactor
            
            if ip_address:  
                json_obj["ip_address"] = ip_address

            vars_json = json.dumps(json_obj)
            commands = [
                "sudo",
                "ansible-playbook",
                "-i",
                "hosts.ini",
                "create-subnet.yml",
                "-l {0}".format(host),
                "-e",
                vars_json
            ]
            p = subprocess.Popen(commands, cwd=self.SOUTHBOUND_DIRECTORY)
            p.wait()
            # print("stderr", stderr)
            # print("retcode =", p.returncode)
            if p.returncode != 0:
                print(
                    "\r\nUnable to run ansible 'create-subnet.yml' for subnet '{0}' in VPC '{1}'\r\n".format(ip_address, vpc_id))
                return False

            result = True
        except Exception as e:
            print(
                "\r\nUnable to physically create the subnet '{0}' for vpc id '{1}'\r\nException below:\r\n{2}".format(ip_address, vpc_id, e))
            result = False

        return result

    def create_in_db(self, vpc_id, ip_address, subnet_name) -> int:

        # create vpc in db
        subnetId_str = self.db.create_subnet(ip_address, subnet_name, vpc_id)
        if(subnetId_str != None):
            return int(subnetId_str)
        else:
            return -1

    def delete_subnet(self, args):
        customer_id = args["customerId"]
        vpc_id = args["vpcId"]
        subnet_id = args["subnetId"]

        # ensure valid customer
        if (self.db.get_customer_by_id(customer_id) == None):
            return {"message": "No customer found with id '{0}'".format(customer_id), "success": False}

        # ensure valid vpc
        vpc = self.db.get_vpc_by_id(vpc_id, customer_id)
        if(vpc == None):
            return {"message": "No vpc found with id '{0}' for customer '{1}'".format(vpc_id, customer_id), "success": False}

        # get subnet
        subnet = self.db.get_subnet_by_id(subnet_id, vpc_id)
        if subnet == None:
            return {"message": "No subnet found with id '{0}' for vpc '{1}'".format(subnet_id, vpc_id), "success": False}

        # Check for no VMs ...and then delete subnets
        vm_list = self.db.get_all_vms(subnet_id)
        if len(vm_list) > 0:
            return {
                "vmList": vm_list,
                "message": "Please delete these VMs (id list given) first!",
                "success": False
            }

        # ...NO VMs were found...

        # delete subnet physically
        phy_result = self.delete_physically(subnet.subnetId, vpc_id, vpc.host)

        # save in db if successful
        if phy_result:
            return self.delete_in_db(subnet_id, subnet.ipAddress, vpc_id, vpc.host)
        else:
            return {
                "message": "Unable to physically delete subnet '{0}' for vpc '{1}' in host '{2}'".format(subnet.ipAddress, vpc_id, vpc.host),
                "success": False
            }

    def delete_physically(self, subnet_id, vpc_id, host):
        # call southbound to delete subnet
        result = False
        host = host.lower()

        try:
            json_obj = {}
            json_obj["subnet_id"] = subnet_id
            json_obj["vpc_id"] = vpc_id

            vars_json = json.dumps(json_obj)
            commands = [
                "sudo",
                "ansible-playbook",
                "-i",
                "hosts.ini",
                "delete-subnet.yml",
                "-l {0}".format(host),
                "-e",
                vars_json
            ]
            p = subprocess.Popen(commands, cwd=self.SOUTHBOUND_DIRECTORY)
            p.wait()
            # print("stderr", stderr)
            # print("retcode =", p.returncode)
            if p.returncode != 0:
                print(
                    "\r\nUnable to run ansible 'delete-subnet.yml' for subnet '{0}' in VPC '{1}'\r\n".format(subnet_id, vpc_id))
                return False

            result = True
        except Exception as e:
            print(
                "\r\nUnable to physically create the subnet '{0}' for vpc id '{1}'\r\nException below:\r\n{2}".format(subnet_id, vpc_id, e))
            result = False

        return result

    def delete_in_db(self, subnet_id, ip_address, vpc_id, host):
        # delete subnet in db
        delete_ok = self.db.delete_subnet(subnet_id)
        if(delete_ok):
            return {
                "message": "subnet '{0}' is deleted from host '{1}'".format(
                    ip_address, host),
                "success": True
            }
        else:
            return {
                "message": "failed to delete subnet '{0}' from host '{1}'".format(
                    ip_address, host),
                "success": False
            }