Exemplo n.º 1
0
class Site(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name':
        ovo_fields.StringField(),
        'status':
        hd_fields.SiteStatusField(default=hd_fields.SiteStatus.Unknown),
        'source':
        hd_fields.ModelSourceField(),
        'tag_definitions':
        ovo_fields.ObjectField('NodeTagDefinitionList', nullable=True),
        'repositories':
        ovo_fields.ObjectField('RepositoryList', nullable=True),
        'authorized_keys':
        ovo_fields.ListOfStringsField(nullable=True),
    }

    def __init__(self, **kwargs):
        super(Site, self).__init__(**kwargs)

    def get_id(self):
        return self.name

    def get_name(self):
        return self.name

    def add_tag_definition(self, tag_definition):
        self.tag_definitions.append(tag_definition)

    def add_key(self, key_string):
        self.authorized_keys.append(key_string)
Exemplo n.º 2
0
class BootAction(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name': ovo_fields.StringField(),
        'source': hd_fields.ModelSourceField(nullable=False),
        'asset_list': ovo_fields.ObjectField('BootActionAssetList',
                                             nullable=False),
        'node_filter': ovo_fields.ObjectField('NodeFilterSet', nullable=True),
        'target_nodes': ovo_fields.ListOfStringsField(nullable=True),
        'signaling': ovo_fields.BooleanField(default=True),
    }

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    # NetworkLink keyed by name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name

    def render_assets(self,
                      nodename,
                      site_design,
                      action_id,
                      design_ref,
                      type_filter=None):
        """Render all of the assets in this bootaction.

        Render the assets of this bootaction and return them in a list.
        The ``nodename`` and ``action_id`` will be
        used to build the context for any assets utilizing the ``template``
        pipeline segment.

        :param nodename: name of the node the assets are destined for
        :param site_design: a objects.SiteDesign instance holding the design sets
        :param action_id: a 128-bit ULID action_id of the boot action
                          the assets are part of
        :param design_ref: the design ref this boot action was initiated under
        :param type_filter: optional filter of the types of assets to render
        """
        assets = list()
        for a in self.asset_list:
            if type_filter is None or (type_filter is not None
                                       and a.type == type_filter):
                a.render(nodename, site_design, action_id, design_ref)
                assets.append(a)

        return assets
Exemplo n.º 3
0
class HardwareProfile(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name':
        ovo_fields.StringField(),
        'source':
        hd_fields.ModelSourceField(),
        'site':
        ovo_fields.StringField(),
        'vendor':
        ovo_fields.StringField(nullable=True),
        'generation':
        ovo_fields.StringField(nullable=True),
        'hw_version':
        ovo_fields.StringField(nullable=True),
        'bios_version':
        ovo_fields.StringField(nullable=True),
        'boot_mode':
        ovo_fields.StringField(nullable=True),
        'bootstrap_protocol':
        ovo_fields.StringField(nullable=True),
        'pxe_interface':
        ovo_fields.StringField(nullable=True),
        'devices':
        ovo_fields.ObjectField('HardwareDeviceAliasList', nullable=True),
    }

    def __init__(self, **kwargs):
        super(HardwareProfile, self).__init__(**kwargs)

        return

    # HardwareProfile keyed on name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name

    def resolve_alias(self, alias_type, alias):
        for d in self.devices:
            if d.alias == alias and d.bus_type == alias_type:
                selector = objects.HardwareDeviceSelector()
                selector.selector_type = "address"
                selector.address = d.address
                selector.device_type = d.dev_type
                return selector

        return None
Exemplo n.º 4
0
class NodeTagDefinition(base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'tag': ovo_fields.StringField(),
        'type': ovo_fields.StringField(),
        'definition': ovo_fields.StringField(),
        'source': hd_fields.ModelSourceField(),
    }

    def __init__(self, **kwargs):
        super(NodeTagDefinition, self).__init__(**kwargs)

    # TagDefinition keyed by tag
    def get_id(self):
        return self.tag
Exemplo n.º 5
0
class HardwareDeviceAlias(base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'alias': ovo_fields.StringField(),
        'source': hd_fields.ModelSourceField(),
        'address': ovo_fields.StringField(),
        'bus_type': ovo_fields.StringField(),
        'dev_type': ovo_fields.StringField(nullable=True),
    }

    def __init__(self, **kwargs):
        super(HardwareDeviceAlias, self).__init__(**kwargs)

    # HardwareDeviceAlias keyed on alias
    def get_id(self):
        return self.alias
Exemplo n.º 6
0
class Rack(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name': obj_fields.StringField(nullable=False),
        'site': obj_fields.StringField(nullable=False),
        'source': hd_fields.ModelSourceField(nullable=False),
        'tor_switches': obj_fields.ObjectField('TorSwitchList',
                                               nullable=False),
        'location': obj_fields.DictOfStringsField(nullable=False),
        'local_networks': obj_fields.ListOfStringsField(nullable=True),
    }

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name
Exemplo n.º 7
0
class HostVolume(base.DrydockObject):
    """Model representing a host logical volume."""

    VERSION = '1.0'

    fields = {
        'name':
        obj_fields.StringField(),
        'source':
        hd_fields.ModelSourceField(),
        'lv_uuid':
        obj_fields.UUIDField(nullable=True),
        'size':
        obj_fields.StringField(nullable=True),
        'mountpoint':
        obj_fields.StringField(nullable=True),
        'fstype':
        obj_fields.StringField(nullable=True, default='ext4'),
        'mount_options':
        obj_fields.StringField(nullable=True, default='defaults'),
        'fs_uuid':
        obj_fields.UUIDField(nullable=True),
        'fs_label':
        obj_fields.StringField(nullable=True),
    }

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    # HostVolume keyed by name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name

    def is_sys(self):
        """Is this LV for root and/or boot?"""
        if self.mountpoint is not None and self.mountpoint in ['/', '/boot']:
            return True
        return False

    """
    Merge two lists of HostVolume models with child_list taking
    priority when conflicts. If a member of child_list has a name
    beginning with '!' it indicates that HostPartition should be
    removed from the merged list
    """

    @staticmethod
    def merge_lists(child_list, parent_list):
        if child_list is None:
            return parent_list

        if parent_list is None:
            return child_list

        effective_list = []

        if len(child_list) == 0 and len(parent_list) > 0:
            for p in parent_list:
                pp = deepcopy(p)
                pp.source = hd_fields.ModelSource.Compiled
                effective_list.append(pp)
        elif len(parent_list) == 0 and len(child_list) > 0:
            for i in child_list:
                if i.get_name().startswith('!'):
                    continue
                else:
                    ii = deepcopy(i)
                    ii.source = hd_fields.ModelSource.Compiled
                    effective_list.append(ii)
        elif len(parent_list) > 0 and len(child_list) > 0:
            inherit_field_list = [
                "lv_uuid",
                "size",
                "mountpoint",
                "fstype",
                "mount_options",
                "fs_uuid",
                "fs_label",
            ]
            parent_volumes = []
            for i in parent_list:
                parent_name = i.get_name()
                parent_volumes.append(parent_name)
                add = True
                for j in child_list:
                    if j.get_name() == ("!" + parent_name):
                        add = False
                        break
                    elif j.get_name() == parent_name:
                        p = objects.HostPartition()
                        p.name = j.get_name()

                        for f in inherit_field_list:
                            setattr(p, f,
                                    objects.Utils.apply_field_inheritance(
                                        getattr(j, f, None),
                                        getattr(i, f, None)))
                        add = False
                        p.source = hd_fields.ModelSource.Compiled
                        effective_list.append(p)
            if add:
                ii = deepcopy(i)
                ii.source = hd_fields.ModelSource.Compiled
                effective_list.append(ii)

        for j in child_list:
            if (j.get_name() not in parent_volumes
                    and not j.get_name().startswith("!")):
                jj = deepcopy(j)
                jj.source = hd_fields.ModelSource.Compiled
                effective_list.append(jj)

        return effective_list
Exemplo n.º 8
0
class HostProfile(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name':
        obj_fields.StringField(nullable=False),
        'site':
        obj_fields.StringField(nullable=False),
        'source':
        hd_fields.ModelSourceField(nullable=False),
        'parent_profile':
        obj_fields.StringField(nullable=True),
        'hardware_profile':
        obj_fields.StringField(nullable=True),
        'oob_type':
        obj_fields.StringField(nullable=True),
        'oob_parameters':
        obj_fields.DictOfStringsField(nullable=True),
        'storage_devices':
        obj_fields.ObjectField('HostStorageDeviceList', nullable=True),
        'volume_groups':
        obj_fields.ObjectField('HostVolumeGroupList', nullable=True),
        'interfaces':
        obj_fields.ObjectField('HostInterfaceList', nullable=True),
        'tags':
        obj_fields.ListOfStringsField(nullable=True),
        'owner_data':
        obj_fields.DictOfStringsField(nullable=True),
        'rack':
        obj_fields.StringField(nullable=True),
        'base_os':
        obj_fields.StringField(nullable=True),
        'image':
        obj_fields.StringField(nullable=True),
        'kernel':
        obj_fields.StringField(nullable=True),
        'kernel_params':
        obj_fields.DictOfStringsField(nullable=True),
        'primary_network':
        obj_fields.StringField(nullable=True),
    }

    def __init__(self, **kwargs):
        super(HostProfile, self).__init__(**kwargs)

    def get_rack(self):
        return self.rack

    # HostProfile is keyed by name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name

    def has_tag(self, tag):
        if tag in self.tags:
            return True

        return False

    def apply_inheritance(self, site_design):
        # No parent to inherit from, just apply design values
        # and return
        if self.parent_profile is None:
            self.source = hd_fields.ModelSource.Compiled
            return

        parent = site_design.get_host_profile(self.parent_profile)

        if parent is None:
            raise NameError("Cannot find parent profile %s for %s" %
                            (self.design['parent_profile'], self.name))

        parent.apply_inheritance(site_design)

        # First compute inheritance for simple fields
        inheritable_field_list = [
            'hardware_profile', 'oob_type', 'storage_layout',
            'bootdisk_device', 'bootdisk_root_size', 'bootdisk_boot_size',
            'rack', 'base_os', 'image', 'kernel', 'primary_network'
        ]

        # Create applied data from self design values and parent
        # applied values

        for f in inheritable_field_list:
            setattr(self, f,
                    objects.Utils.apply_field_inheritance(
                        getattr(self, f, None), getattr(parent, f, None)))

        # Now compute inheritance for complex types
        self.oob_parameters = objects.Utils.merge_dicts(
            self.oob_parameters, parent.oob_parameters)

        self.tags = objects.Utils.merge_lists(self.tags, parent.tags)

        self.owner_data = objects.Utils.merge_dicts(self.owner_data,
                                                    parent.owner_data)

        self.kernel_params = objects.Utils.merge_dicts(self.kernel_params,
                                                       parent.kernel_params)

        self.storage_devices = HostStorageDeviceList.from_basic_list(
            HostStorageDevice.merge_lists(self.storage_devices,
                                          parent.storage_devices))

        self.volume_groups = HostVolumeGroupList.from_basic_list(
            HostVolumeGroup.merge_lists(self.volume_groups,
                                        parent.volume_groups))

        self.interfaces = HostInterfaceList.from_basic_list(
            HostInterface.merge_lists(self.interfaces, parent.interfaces))

        self.source = hd_fields.ModelSource.Compiled

        return
Exemplo n.º 9
0
class HostInterface(base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'device_name':
        obj_fields.StringField(),
        'source':
        hd_fields.ModelSourceField(),
        'network_link':
        obj_fields.StringField(nullable=True),
        'hardware_slaves':
        obj_fields.ListOfStringsField(nullable=True),
        'slave_selectors':
        obj_fields.ObjectField('HardwareDeviceSelectorList', nullable=True),
        'networks':
        obj_fields.ListOfStringsField(nullable=True),
    }

    def __init__(self, **kwargs):
        super(HostInterface, self).__init__(**kwargs)

    # HostInterface is keyed by device_name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.device_name

    def get_hw_slaves(self):
        return self.hardware_slaves

    def get_slave_selectors(self):
        return self.slave_selectors

    # Return number of slaves for this interface
    def get_slave_count(self):
        return len(self.hardware_slaves)

    # The device attribute may be hardware alias that translates to a
    # physical device address. If the device attribute does not match an
    # alias, we assume it directly identifies a OS device name. When the
    # apply_hardware_profile method is called on the parent Node of this
    # device, the selector will be decided and applied

    def add_selector(self, slave_selector):
        if self.slave_selectors is None:
            self.slave_selectors = objects.HardwareDeviceSelectorList()

        self.slave_selectors.append(slave_selector)

    """
    Merge two lists of HostInterface models with child_list taking
    priority when conflicts. If a member of child_list has a device_name
    beginning with '!' it indicates that HostInterface should be
    removed from the merged list
    """

    @staticmethod
    def merge_lists(child_list, parent_list):
        if child_list is None:
            return parent_list

        if parent_list is None:
            return child_list

        effective_list = []

        if len(child_list) == 0 and len(parent_list) > 0:
            for p in parent_list:
                pp = deepcopy(p)
                pp.source = hd_fields.ModelSource.Compiled
                effective_list.append(pp)
        elif len(parent_list) == 0 and len(child_list) > 0:
            for i in child_list:
                if i.get_name().startswith('!'):
                    continue
                else:
                    ii = deepcopy(i)
                    ii.source = hd_fields.ModelSource.Compiled
                    effective_list.append(ii)
        elif len(parent_list) > 0 and len(child_list) > 0:
            parent_interfaces = []
            for i in parent_list:
                parent_name = i.get_name()
                parent_interfaces.append(parent_name)
                add = True
                for j in child_list:
                    if j.get_name() == ("!" + parent_name):
                        add = False
                        break
                    elif j.get_name() == parent_name:
                        m = objects.HostInterface()
                        m.device_name = j.get_name()

                        m.network_link = \
                            objects.Utils.apply_field_inheritance(
                                getattr(j, 'network_link', None),
                                getattr(i, 'network_link', None))

                        s = [
                            x for x in getattr(i, 'hardware_slaves', [])
                            if ("!" + x
                                ) not in getattr(j, 'hardware_slaves', [])
                        ]

                        s.extend([
                            x for x in getattr(j, 'hardware_slaves', [])
                            if not x.startswith("!")
                        ])

                        m.hardware_slaves = s

                        n = [
                            x for x in getattr(i, 'networks', [])
                            if ("!" + x) not in getattr(j, 'networks', [])
                        ]

                        n.extend([
                            x for x in getattr(j, 'networks', [])
                            if not x.startswith("!")
                        ])

                        m.networks = n
                        m.source = hd_fields.ModelSource.Compiled

                        effective_list.append(m)
                        add = False
                        break

                if add:
                    ii = deepcopy(i)
                    ii.source = hd_fields.ModelSource.Compiled
                    effective_list.append(ii)

            for j in child_list:
                if (j.device_name not in parent_interfaces
                        and not j.get_name().startswith("!")):
                    jj = deepcopy(j)
                    jj.source = hd_fields.ModelSource.Compiled
                    effective_list.append(jj)

        return effective_list
Exemplo n.º 10
0
class HardwareProfile(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name':
        ovo_fields.StringField(),
        'source':
        hd_fields.ModelSourceField(),
        'site':
        ovo_fields.StringField(),
        'vendor':
        ovo_fields.StringField(nullable=True),
        'generation':
        ovo_fields.StringField(nullable=True),
        'hw_version':
        ovo_fields.StringField(nullable=True),
        'bios_version':
        ovo_fields.StringField(nullable=True),
        'boot_mode':
        ovo_fields.StringField(nullable=True),
        'bootstrap_protocol':
        ovo_fields.StringField(nullable=True),
        'pxe_interface':
        ovo_fields.StringField(nullable=True),
        'devices':
        ovo_fields.ObjectField('HardwareDeviceAliasList', nullable=True),
        'cpu_sets':
        ovo_fields.DictOfStringsField(nullable=True),
        'hugepages_confs':
        ovo_fields.ObjectField('HugepagesConfList', nullable=True),
    }

    def __init__(self, **kwargs):
        super(HardwareProfile, self).__init__(**kwargs)

        return

    # HardwareProfile keyed on name
    def get_id(self):
        return self.get_name()

    def get_name(self):
        return self.name

    def get_hugepage_conf(self, conf_name):
        """Return the hugepages conf matching ``conf_name``"""
        if not self.hugepages_confs:
            raise errors.HugepageConfNotFound(
                "Hugepage configuration %s not found." % conf_name)

        for c in self.hugepages_confs:
            if c.name == conf_name:
                return c

        raise errors.HugepageConfNotFound(
            "Hugepage configuration %s not found." % conf_name)

    def get_cpu_set(self, set_name):
        """Return the cpu set matching ``set_name``"""
        if not self.cpu_sets:
            raise errors.CpuSetNotFound("CPU set %s not found." % set_name)

        if set_name in self.cpu_sets:
            return self.cpu_sets[set_name]

        raise errors.CpuSetNotFound("CPU set %s not found." % set_name)

    def resolve_alias(self, alias_type, alias):
        for d in self.devices:
            if d.alias == alias and d.bus_type == alias_type:
                selector = objects.HardwareDeviceSelector()
                selector.selector_type = "address"
                selector.address = d.address
                selector.device_type = d.dev_type
                return selector

        return None
Exemplo n.º 11
0
class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'id':
        ovo_fields.UUIDField(),
        # if null, indicates this is the site base design
        'base_design_id':
        ovo_fields.UUIDField(nullable=True),
        'source':
        hd_fields.ModelSourceField(),
        'site':
        ovo_fields.ObjectField('Site', nullable=True),
        'networks':
        ovo_fields.ObjectField('NetworkList', nullable=True),
        'network_links':
        ovo_fields.ObjectField('NetworkLinkList', nullable=True),
        'host_profiles':
        ovo_fields.ObjectField('HostProfileList', nullable=True),
        'hardware_profiles':
        ovo_fields.ObjectField('HardwareProfileList', nullable=True),
        'baremetal_nodes':
        ovo_fields.ObjectField('BaremetalNodeList', nullable=True),
        'prom_configs':
        ovo_fields.ObjectField('PromenadeConfigList', nullable=True),
        'racks':
        ovo_fields.ObjectField('RackList', nullable=True),
    }

    def __init__(self, **kwargs):
        super(SiteDesign, self).__init__(**kwargs)

    # Assign UUID id
    def assign_id(self):
        self.id = uuid.uuid4()
        return self.id

    # SiteDesign Keyed by id
    def get_id(self):
        return self.id

    def get_site(self):
        return self.site

    def set_site(self, site):
        self.site = site

    def add_network(self, new_network):
        if new_network is None:
            raise errors.DesignError("Invalid Network model")

        if self.networks is None:
            self.networks = objects.NetworkList()

        self.networks.append(new_network)

    def get_network(self, network_key):
        for n in self.networks:
            if n.get_id() == network_key:
                return n

        raise errors.DesignError(
            "Network %s not found in design state" % network_key)

    def add_network_link(self, new_network_link):
        if new_network_link is None:
            raise errors.DesignError("Invalid NetworkLink model")

        if self.network_links is None:
            self.network_links = objects.NetworkLinkList()

        self.network_links.append(new_network_link)

    def get_network_link(self, link_key):
        for l in self.network_links:
            if l.get_id() == link_key:
                return l

        raise errors.DesignError(
            "NetworkLink %s not found in design state" % link_key)

    def add_rack(self, new_rack):
        if new_rack is None:
            raise errors.DesignError("Invalid Rack model")

        if self.racks is None:
            self.racks = objects.RackList()

        self.racks.append(new_rack)

    def get_rack(self, rack_key):
        for r in self.racks:
            if r.get_id() == rack_key:
                return r
        raise errors.DesignError(
            "Rack %s not found in design state" % rack_key)

    def add_host_profile(self, new_host_profile):
        if new_host_profile is None:
            raise errors.DesignError("Invalid HostProfile model")

        if self.host_profiles is None:
            self.host_profiles = objects.HostProfileList()

        self.host_profiles.append(new_host_profile)

    def get_host_profile(self, profile_key):
        for p in self.host_profiles:
            if p.get_id() == profile_key:
                return p

        raise errors.DesignError(
            "HostProfile %s not found in design state" % profile_key)

    def add_hardware_profile(self, new_hardware_profile):
        if new_hardware_profile is None:
            raise errors.DesignError("Invalid HardwareProfile model")

        if self.hardware_profiles is None:
            self.hardware_profiles = objects.HardwareProfileList()

        self.hardware_profiles.append(new_hardware_profile)

    def get_hardware_profile(self, profile_key):
        for p in self.hardware_profiles:
            if p.get_id() == profile_key:
                return p

        raise errors.DesignError(
            "HardwareProfile %s not found in design state" % profile_key)

    def add_baremetal_node(self, new_baremetal_node):
        if new_baremetal_node is None:
            raise errors.DesignError("Invalid BaremetalNode model")

        if self.baremetal_nodes is None:
            self.baremetal_nodes = objects.BaremetalNodeList()

        self.baremetal_nodes.append(new_baremetal_node)

    def get_baremetal_node(self, node_key):
        for n in self.baremetal_nodes:
            if n.get_id() == node_key:
                return n

        raise errors.DesignError(
            "BaremetalNode %s not found in design state" % node_key)

    def add_promenade_config(self, prom_conf):
        if self.prom_configs is None:
            self.prom_configs = objects.PromenadeConfigList()

        self.prom_configs.append(prom_conf)

    def get_promenade_configs(self):
        return self.prom_configs

    def get_promenade_config(self, target_list):
        targeted_docs = []

        if target_list is None or not isinstance(target_list, list):
            return targeted_docs

        for t in target_list:
            targeted_docs.extend(self.prom_configs.select_for_target(t))

        return targeted_docs

    def create(self, ctx, state_manager):
        self.created_at = datetime.datetime.now()
        self.created_by = ctx.user

        state_manager.post_design(self)

    def save(self, ctx, state_manager):
        self.updated_at = datetime.datetime.now()
        self.updated_by = ctx.user

        state_manager.put_design(self)

    """
    Support filtering on rack name, node name or node tag
    for now. Each filter can be a comma-delimited list of
    values. The final result is an intersection of all the
    filters
    """

    def get_filtered_nodes(self, node_filter):
        effective_nodes = self.baremetal_nodes

        # filter by rack
        rack_filter = node_filter.get('rackname', None)

        if rack_filter is not None:
            rack_list = rack_filter.split(',')
            effective_nodes = [
                x for x in effective_nodes if x.get_rack() in rack_list
            ]
        # filter by name
        name_filter = node_filter.get('nodename', None)

        if name_filter is not None:
            name_list = name_filter.split(',')
            effective_nodes = [
                x for x in effective_nodes if x.get_name() in name_list
            ]
        # filter by tag
        tag_filter = node_filter.get('tags', None)

        if tag_filter is not None:
            tag_list = tag_filter.split(',')
            effective_nodes = [
                x for x in effective_nodes for t in tag_list if x.has_tag(t)
            ]

        return effective_nodes
Exemplo n.º 12
0
class HostPartition(base.DrydockObject):

    VERSION = '1.0'

    fields = {
        'name':         obj_fields.StringField(),
        'source':       hd_fields.ModelSourceField(),
        'device':       obj_fields.StringField(nullable=True),
        'part_uuid':    obj_fields.UUIDField(nullable=True),
        'size':         obj_fields.StringField(nullable=True),
        'mountpoint':   obj_fields.StringField(nullable=True),
        'fstype':       obj_fields.StringField(nullable=True, default='ext4'),
        'mount_options': obj_fields.StringField(nullable=True, default='defaults'),
        'fs_uuid':      obj_fields.UUIDField(nullable=True),
        'fs_label':     obj_fields.StringField(nullable=True),
        'selector':     obj_fields.ObjectField('HardwareDeviceSelector',
                                           nullable=True),
    }

    def __init__(self, **kwargs):
        super(HostPartition, self).__init__(**kwargs)

    def get_device(self):
        return self.device

    # HostPartition keyed by name
    def get_id(self):
        return self.get_name()
        
    def get_name(self):
        return self.name

    # The device attribute may be hardware alias that translates to a
    # physical device address. If the device attribute does not match an
    # alias, we assume it directly identifies a OS device name. When the
    # apply_hardware_profile method is called on the parent Node of this
    # device, the selector will be decided and applied

    def set_selector(self, selector):
        self.selector = selector

    def get_selector(self):
        return self.selector

    """
    Merge two lists of HostPartition models with child_list taking
    priority when conflicts. If a member of child_list has a name
    beginning with '!' it indicates that HostPartition should be
    removed from the merged list
    """

    @staticmethod
    def merge_lists(child_list, parent_list):
        effective_list = []

        if len(child_list) == 0 and len(parent_list) > 0:
            for p in parent_list:
                pp = deepcopy(p)
                pp.source = hd_fields.ModelSource.Compiled
                effective_list.append(pp)
        elif len(parent_list) == 0 and len(child_list) > 0:
            for i in child_list:
                if i.get_name().startswith('!'):
                    continue
                else:
                    ii = deepcopy(i)
                    ii.source = hd_fields.ModelSource.Compiled
                    effective_list.append(ii)
        elif len(parent_list) > 0 and len(child_list) > 0:
            inherit_field_list = ["device", "part_uuid", "size",
                                  "mountpoint", "fstype", "mount_options",
                                  "fs_uuid", "fs_label"]
            parent_partitions = []
            for i in parent_list:
                parent_name = i.get_name()
                parent_partitions.append(parent_name)
                add = True
                for j in child_list:
                    if j.get_name() == ("!" + parent_name):
                        add = False
                        break
                    elif j.get_name() == parent_name:
                        p = objects.HostPartition()
                        p.name = j.get_name()

                        for f in inherit_field_list:
                            setattr(p, f,
                                objects.Utils.apply_field_inheritance(getattr(j, f, None),
                                                                      getattr(i, f, None)))
                        add = False
                        p.source = hd_fields.ModelSource.Compiled
                        effective_list.append(p)
            if add:
                ii = deepcopy(i)
                ii.source = hd_fields.ModelSource.Compiled
                effective_list.append(ii)

        for j in child_list:
            if (j.get_name() not in parent_list and
                not j.get_name().startswith("!")):
                jj = deepcopy(j)
                jj.source = hd_fields.ModelSource.Compiled
                effective_list.append(jj)

        return effective_list