Exemple #1
0
def get_heat_json_from_topology_config(config):
    """
    Generates heat template from the topology configuration object
    use load_config_from_topology_json to get the configuration from the Topology
    :param config: configuration dict from load_config_from_topology_json
    :return: json encoded heat template as String
    """

    template = dict()
    template["heat_template_version"] = "2013-05-23"
    template["resources"] = dict()

    for network in config["networks"]:
        nr = dict()
        nr["type"] = "OS::Neutron::Net"

        nrp = dict()
        nrp["shared"] = False
        nrp["name"] = network["name"]
        nrp["admin_state_up"] = True

        nr["properties"] = nrp

        nrs = dict()
        nrs["type"] = "OS::Neutron::Subnet"

        p = dict()
        p["cidr"] = "1.1.1.0/24"
        p["enable_dhcp"] = False
        p["name"] = network["name"] + "_subnet"
        if network["name"] == "virbr0":
            p["network_id"] = configuration.openstack_mgmt_network
        elif network["name"] == configuration.openstack_external_network:
            p["network_id"] = configuration.openstack_external_network
        else:
            p["network_id"] = {"get_resource": network["name"]}

        nrs["properties"] = p

        template["resources"][network["name"]] = nr
        template["resources"][network["name"] + "_subnet"] = nrs

    # cache the image_details here to avoid multiple REST calls for details about an image type
    # as many topologies have lots of the same types of images around
    image_details_dict = dict()

    for device in config["devices"]:

        if device["imageId"] in image_details_dict:
            image_details = image_details_dict[device["imageId"]]
        else:
            image_details = imageUtils.get_image_detail(device["imageId"])
            image_details_dict[device["imageId"]] = image_details

        image_name = image_details["name"]
        if "disk" in image_details:
            image_disk = image_details["disk"]
        else:
            image_disk = 20

        # determine openstack flavor here
        device_ram = int(device["ram"])
        device_cpu = int(device["cpu"])

        flavor_detail = openstackUtils.get_minimum_flavor_for_specs(configuration.openstack_project,
                                                                    device_cpu,
                                                                    device_ram,
                                                                    image_disk
                                                                    )

        flavor = flavor_detail["name"]

        dr = dict()
        dr["type"] = "OS::Nova::Server"
        dr["properties"] = dict()
        dr["properties"]["flavor"] = flavor
        dr["properties"]["networks"] = []
        index = 0
        for p in device["interfaces"]:
            port = dict()
            port["port"] = dict()
            port["port"]["get_resource"] = device["name"] + "_port" + str(index)
            index += 1
            dr["properties"]["networks"].append(port)

        dr["properties"]["image"] = image_name
        dr["properties"]["name"] = device["name"]

        if device["configDriveSupport"]:
            dr["properties"]["config_drive"] = True
            dr["properties"]["user_data_format"] = "RAW"
            metadata = dict()
            metadata["hostname"] = device["name"]
            metadata["console"] = "vidconsole"
            dr["properties"]["metadata"] = metadata

            # let's check all the configDriveParams and look for a junos config
            # FIXME - this may need tweaked if we need to include config drive cloud-init support for other platforms
            # right now we just need to ignore /boot/loader.conf
            for cfp in device["configDriveParams"]:

                if "destination" in cfp and cfp["destination"] == "/boot/loader.conf":
                    template_name = cfp["template"]
                    loader_string = osUtils.compile_config_drive_params_template(template_name,
                                                                                 device["name"],
                                                                                 device["label"],
                                                                                 device["password"],
                                                                                 device["ip"],
                                                                                 device["managementInterface"])

                    for l in loader_string:
                        left, right = l.split('=')
                        if left not in metadata:
                            metadata[left] = right

                if "destination" in cfp and cfp["destination"] == "/juniper.conf":
                    template_name = cfp["template"]
                    personality_string = osUtils.compile_config_drive_params_template(template_name,
                                                                                      device["name"],
                                                                                      device["label"],
                                                                                      device["password"],
                                                                                      device["ip"],
                                                                                      device["managementInterface"])

                    dr["properties"]["personality"] = dict()
                    dr["properties"]["personality"] = {"/config/juniper.conf": personality_string}

        template["resources"][device["name"]] = dr

    for device in config["devices"]:
        index = 0
        for port in device["interfaces"]:
            pr = dict()
            pr["type"] = "OS::Neutron::Port"
            p = dict()

            if port["bridge"] == "virbr0":
                p["network_id"] = configuration.openstack_mgmt_network
            elif port["bridge"] == configuration.openstack_external_network:
                p["network_id"] = configuration.openstack_external_network
            else:
                p["network_id"] = {"get_resource": port["bridge"]}

            pr["properties"] = p
            template["resources"][device["name"] + "_port" + str(index)] = pr
            index += 1

    return json.dumps(template)
Exemple #2
0
def create_disk_instance(device, disk_params):
    """
    Creates a disk according to the parameters specified.
    Can be blank, image, or config_drive

    :param device: device dictionary created from wistarUtils.loadJson()
    :param disk_params: parameters for the specific disk we are working with
    :return: the path to the created disk or ""
    """

    domain_name = device["name"]
    disk_instance_path = ""

    if "type" in disk_params:
        if disk_params["type"] == "image" and "image_id" in disk_params:
            logger.debug("Creating secondary/tertiary Disk information")
            image_id = disk_params["image_id"]
            disk_image = Image.objects.get(pk=image_id)
            disk_base_path = settings.MEDIA_ROOT + "/" + disk_image.filePath.url

            disk_instance_path = osUtils.get_instance_path_from_image(disk_base_path,
                                                                      domain_name + "_secondary_image.img"
                                                                      )

            if not osUtils.check_path(disk_instance_path):
                if not osUtils.create_thin_provision_instance(disk_base_path,
                                                              domain_name + "_secondary_image.img"
                                                              ):
                    raise Exception("Could not create image instance for image: " + disk_base_path)

        elif disk_params["type"] == "blank":
            disk_instance_path = settings.MEDIA_ROOT \
                                 + "/user_images/instances/" + domain_name + "_secondary_blank.img"

            disk_size = "16G"
            if "size" in disk_params:
                disk_size = disk_params["size"]

            if not osUtils.check_path(disk_instance_path):
                if not osUtils.create_blank_image(disk_instance_path, disk_size):
                    raise Exception("Could not create image instance for image: " + disk_instance_path)

        elif disk_params["type"] == "config_drive":
            # let's check if config_drive is supported for this vm_type!
            # this is usually used for vMX in openstack, however, we can also use it here for KVM deployments
            disk_instance_path = ''
            if "configDriveSupport" in device and device["configDriveSupport"] is True:

                logger.debug("Lets create a config-drive!")

                # keep a dict of files with format: filename: filecontents
                files = dict()
                params = device["configDriveParams"]
                if "configDriveParamsFile" in device and device["configDriveParamsFile"]:
                    logger.debug("Using inline config_drive format")
                    # behavior change 12-28-2016 - allow passing a list of templates and destinations
                    # instead of defining the params directly on the device object
                    # if the configDriveParams is a dict, then this is an older topology, leave this code here
                    # to still support them - otherwise fall through to the isinstance check for list type for
                    # newer style configuration
                    if isinstance(params, dict):
                        name = device["configDriveParamsFile"]
                        file_data = ""
                        # config drive params are usually a dict - to make json serialization easier
                        # for our purposes here, let's just make a file with a single key: value per line
                        # note, we can add a serialization format to the vm_type.js if needed here
                        # only currently used for /boot/loader.conf in vmx and riot
                        for k in params:
                            file_data += '%s="%s"\n' % (k, params[k])

                        files[name] = file_data

                        # junos customization
                        # let's also inject a default config here as well if possible!
                        if "junos" in device["type"]:
                            logger.debug("Creating Junos configuration template")
                            junos_config = osUtils.get_junos_default_config_template(device["name"],
                                                                                     device["label"],
                                                                                     device["password"],
                                                                                     device["ip"],
                                                                                     device["managementInterface"])

                            if junos_config is not None:
                                files["/juniper.conf"] = junos_config

                # check for new (12-28-2016) style config drive params definition
                if isinstance(params, list):
                    logger.debug("params is a list")
                    for p in params:
                        if "template" in p and "destination" in p:
                            file_data = None
                            file_data = osUtils.compile_config_drive_params_template(
                                p["template"],
                                device["name"],
                                device["label"],
                                device["password"],
                                device["ip"],
                                device["managementInterface"]
                            )
                            if file_data is not None:
                                files[p["destination"]] = file_data

                disk_instance_path = osUtils.create_config_drive(device["name"], files)
                if disk_instance_path is None:
                    disk_instance_path = ''

    logger.debug("Using %s" % disk_instance_path)
    return disk_instance_path
Exemple #3
0
def get_heat_json_from_topology_config(config,
                                       project_name='admin',
                                       use_volumes=False):
    """
    Generates heat template from the topology configuration object
    use load_config_from_topology_json to get the configuration from the Topology
    :param config: configuration dict from load_config_from_topology_json
    :return: json encoded heat template as String
    """

    template = dict()
    template["heat_template_version"] = "2013-05-23"
    template["resources"] = dict()

    for network in config["networks"]:
        nr = dict()
        nr["type"] = "OS::Neutron::Net"

        nrp = dict()
        nrp["shared"] = False
        nrp["name"] = network["name"]
        nrp["admin_state_up"] = True

        nr["properties"] = nrp

        nrs = dict()
        nrs["type"] = "OS::Neutron::Subnet"
        #
        p = dict()
        p["cidr"] = "1.1.1.0/24"
        p["enable_dhcp"] = False
        p["gateway_ip"] = ""
        p["name"] = network["name"] + "_subnet"
        if network["name"] == "virbr0":
            p["network_id"] = configuration.openstack_mgmt_network
        elif network["name"] == configuration.openstack_external_network:
            p["network_id"] = configuration.openstack_external_network
        else:
            p["network_id"] = {"get_resource": network["name"]}

        nrs["properties"] = p

        template["resources"][network["name"]] = nr
        template["resources"][network["name"] + "_subnet"] = nrs

    # cache the image_details here to avoid multiple REST calls for details about an image type
    # as many topologies have lots of the same types of images around
    image_details_dict = dict()

    for device in config["devices"]:

        if device["imageId"] in image_details_dict:
            image_details = image_details_dict[device["imageId"]]
        else:
            image_details = imageUtils.get_image_detail(device["imageId"])
            image_details_dict[device["imageId"]] = image_details

        image_name = image_details["name"]

        # This should take into account the actual size of the fpc
        image_disk_size = 4

        # set the size in GB, rounding up to the nearest int
        if 'size' in image_details:
            current_size = float(image_details['size'])
            image_disk_size = int(math.ceil(current_size / 1000000000))

        # if the glance image asks for a minimum disk size, let's see if it's larger that what we have
        if "min_disk" in image_details and image_details[
                'min_disk'] > image_disk_size:
            image_disk_size = image_details["min_disk"]

        # if the user has specified a desired disk size, grab it here so we get the correct flavor
        if type(image_disk_size
                ) is int and device["resizeImage"] > image_disk_size:
            image_disk_size = device["resizeImage"]

        # determine openstack flavor here
        device_ram = int(device["ram"])
        device_cpu = int(device["cpu"])

        # FIXME get_minimum_flavor should ignore the disk size if a volume is used
        # Also ignore the disk size of a flavor if the min_disk is 0 (since its an ephemeral topology)
        flavor_detail = None
        required_disk = 0
        if configuration.openstack_use_volumes:
            # Using a volume
            required_disk = 0
        elif "min_disk" in image_details and image_details["min_disk"] == 0:
            # Ephemeral, only using as much as the qcow2 images need
            required_disk = 0
        else:
            required_disk = image_disk_size

        flavor_detail = openstackUtils.get_minimum_flavor_for_specs(
            configuration.openstack_project, device_cpu, device_ram,
            required_disk)

        flavor = flavor_detail["name"]

        dr = dict()
        dr["type"] = "OS::Nova::Server"
        dr["properties"] = dict()
        dr["properties"]["flavor"] = flavor
        dr["properties"]["networks"] = []
        index = 0
        for p in device["interfaces"]:
            port = dict()
            port["port"] = dict()
            port["port"]["get_resource"] = device["name"] + "_port" + str(
                index)
            index += 1
            dr["properties"]["networks"].append(port)

        # When we don't want to use ephemeral node storage
        # Create volume that the OS::Nova::Server instance depends on
        # Don't create a volume if the min-disk for the image is 0
        if configuration.openstack_use_volumes == False:
            dr["properties"]["image"] = image_name
        elif "min_disk" in image_details and image_details["min_disk"] == 0:
            dr["properties"]["image"] = image_name
        else:
            # Create a volume resource
            vr = {}
            vr["type"] = "OS::Cinder::Volume"
            vr["properties"] = {}
            vr["properties"]["size"] = image_disk_size
            vr_name = device["name"] + "_vol0"
            vr["properties"]["image"] = image_name
            template["resources"][vr_name] = vr

            # Add the block device mapping
            # vda as a device name should work for most devices
            dr["properties"]["block_device_mapping"] = [{
                "device_name":
                "vda",
                "volume_id": {
                    "get_resource": vr_name
                },
                "delete_on_termination":
                "true"
            }]

        if device["configDriveSupport"]:
            dr["properties"]["config_drive"] = True
            dr["properties"]["user_data_format"] = "RAW"
            metadata = dict()
            metadata["hostname"] = device["name"]
            metadata["console"] = "vidconsole"
            dr["properties"]["metadata"] = metadata

            # let's check all the configDriveParams and look for a junos config
            # FIXME - this may need tweaked if we need to include config drive cloud-init support for other platforms
            # right now we just need to ignore /boot/loader.conf
            for cfp in device["configDriveParams"]:

                if "destination" in cfp and cfp[
                        "destination"] == "/boot/loader.conf":
                    logger.debug("Creating loader.conf config-drive entry")
                    template_name = cfp["template"]
                    loader_string = osUtils.compile_config_drive_params_template(
                        template_name, device["name"], device["label"],
                        device["password"], device["ip"],
                        device["managementInterface"])

                    logger.debug('----------')
                    logger.debug(loader_string)
                    logger.debug('----------')
                    for l in loader_string.split('\n'):
                        if '=' in l:
                            left, right = l.split('=')
                            if left not in metadata and left != '':
                                metadata[left] = right.replace('"', '')

                if "destination" in cfp and cfp[
                        "destination"] == "/juniper.conf":
                    logger.debug("Creating juniper.conf config-drive entry")
                    template_name = cfp["template"]
                    personality_string = osUtils.compile_config_drive_params_template(
                        template_name, device["name"], device["label"],
                        device["password"], device["ip"],
                        device["managementInterface"])

                    dr["properties"]["personality"] = dict()
                    dr["properties"]["personality"] = {
                        "/config/juniper.conf": personality_string
                    }
                else:
                    logger.debug('No juniper.conf found here ')

        if device['cloudInitSupport']:
            logger.debug('creating cloud-init script')
            dr["properties"]["config_drive"] = True
            dr["properties"]["user_data_format"] = "RAW"
            metadata = dict()
            metadata["hostname"] = device["name"]
            dr["properties"]["metadata"] = metadata
            # grab the prefix len from the management subnet which is in the form 192.168.122.0/24
            if '/' in configuration.management_subnet:
                management_prefix_len = configuration.management_subnet.split(
                    '/')[1]
            else:
                management_prefix_len = '24'

            management_ip = device['ip'] + '/' + management_prefix_len

            device_config = osUtils.get_cloud_init_config(
                device['name'], device['label'], management_ip,
                device['managementInterface'], device['password'])

            script_string = ""
            if "configScriptId" in device and device["configScriptId"] != 0:
                logger.debug("Passing script data!")
                try:
                    script = Script.objects.get(
                        pk=int(device["configScriptId"]))
                    script_string = script.script
                    device_config["script_param"] = device.get(
                        "configScriptParam", '')
                    logger.debug(script_string)
                except ObjectDoesNotExist:
                    logger.info(
                        'config script was specified but was not found!')

            user_data_string = osUtils.render_cloud_init_user_data(
                device_config, script_string)
            dr["properties"]["user_data"] = user_data_string

        template["resources"][device["name"]] = dr

    for device in config["devices"]:
        index = 0
        for port in device["interfaces"]:
            pr = dict()
            pr["type"] = "OS::Neutron::Port"
            p = dict()

            if port["bridge"] == "virbr0":
                p["network_id"] = configuration.openstack_mgmt_network

                # specify our desired IP address on the management interface
                p['fixed_ips'] = list()
                fip = dict()
                fip['ip_address'] = device['ip']
                p['fixed_ips'].append(fip)

            elif port["bridge"] == configuration.openstack_external_network:
                p["network_id"] = configuration.openstack_external_network
            else:
                p["network_id"] = {"get_resource": port["bridge"]}
                # disable port security on all other ports (in case this isn't set globally)
                p['port_security_enabled'] = False

            pr["properties"] = p
            template["resources"][device["name"] + "_port" + str(index)] = pr
            index += 1

    return json.dumps(template)