Example #1
0
    def __convert_nodes_to_TortugaObjectList(
            self, nodes: List[NodeModel],
            optionDict: Optional[OptionsDict] = None) -> TortugaObjectList:
        """
        Return TortugaObjectList of nodes with relations populated

        :param nodes:      list of Node objects
        :param optionDict:
        :param deleting:   whether or not to include nodes in the deleting
                           state

        :return: TortugaObjectList

        """
        nodeList = TortugaObjectList()

        for node in nodes:
            self.loadRelations(node, optionDict)

            # ensure 'resourceadapter' relation is always loaded. This one
            # is special since it's a relationship inside of a relationship.
            # It needs to be explicitly defined.
            self.loadRelation(node.hardwareprofile, 'resourceadapter')

            nodeList.append(Node.getFromDbDict(node.__dict__))

        return nodeList
Example #2
0
    def getNode(self,
                name: str,
                optionDict: Optional[Union[dict, None]] = None):
        """
        Get node from the db.

            Returns:
                node
            Throws:
                NodeNotFound
                DbError
        """

        session = DbManager().openSession()

        try:
            dbNode = self._nodesDbHandler.getNode(session, name)

            self.loadRelations(dbNode, optionDict)

            self.loadRelations(dbNode, {
                'softwareprofile': True,
                'hardwareprofile': True,
                'tags': True,
            })

            return Node.getFromDbDict(dbNode.__dict__)
        except TortugaException as ex:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
        finally:
            DbManager().closeSession()
Example #3
0
    def getNodeList(self, session: Session,
                    softwareProfile: SoftwareProfile) -> TortugaObjectList:
        """
        Get list of nodes in 'softwareProfile'

            Returns:
                [node]
            Throws:
                DbError
        """

        try:
            dbSoftwareProfile = \
                self._softwareProfilesDbHandler.getSoftwareProfile(
                    session, softwareProfile)

            nodeList = TortugaObjectList()

            for dbNode in dbSoftwareProfile.nodes:
                self.loadRelation(dbNode, 'hardwareprofile')

                nodeList.append(Node.getFromDbDict(dbNode.__dict__))

            return nodeList
        except TortugaException:
            raise
        except Exception as ex:
            self._logger.exception(str(ex))
            raise
Example #4
0
    def getNodeList(self, softwareProfile):
        """
        Get list of nodes in 'softwareProfile'

            Returns:
                [node]
            Throws:
                DbError
        """

        session = DbManager().openSession()

        try:
            dbSoftwareProfile = self._softwareProfilesDbHandler.\
                getSoftwareProfile(session, softwareProfile)

            nodeList = TortugaObjectList()

            for dbNode in dbSoftwareProfile.nodes:
                self.loadRelation(dbNode, 'hardwareprofile')

                nodeList.append(Node.getFromDbDict(dbNode.__dict__))

            return nodeList
        except TortugaException as ex:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
        finally:
            DbManager().closeSession()
Example #5
0
def test_getFromDbDict():
    nodeDbDict = {
        'id': 1235,
        'name': 'mike',
    }

    tmpnode = Node.getFromDbDict(nodeDbDict)

    assert tmpnode.getName() == 'mike'
Example #6
0
def test_node_getFromJson():
    nodedict = {
        'name': 'mike',
    }

    jsonstr = json.dumps(nodedict)

    tmpnode = Node.getFromJson(jsonstr)

    assert tmpnode.getName() == 'mike'
Example #7
0
    def getUsableNodes(self, softwareProfileName):
        url = 'v1/softwareProfiles/%s/usable' % (
            urllib.parse.quote_plus(softwareProfileName))

        try:
            _, responseDict = self.sendSessionRequest(url)

            return Node.getListFromDict(responseDict)
        except TortugaException as ex:
            raise
        except Exception as ex:
            raise TortugaException(exception=ex)
Example #8
0
    def fire_state_change_event(self, db_node: Node, previous_state: str):
        """
        Fires a node state changed event. This is a "fake" operation allowing
        resource adapters to fire events without having to actually take
        the node through the actual state change. The node is assumed to
        have it's current state set to the new state.

        :param Node db_node:       a database node instance
        :param str previous_state: the previous state for the node

        """
        node_dict = TortugaNode.getFromDbDict(db_node.__dict__).getCleanDict()
        NodeStateChanged.fire(node=node_dict, previous_state=previous_state)
Example #9
0
    def getNodeByIp(self, ip):
        session = DbManager().openSession()

        try:
            node = self._nodesDbHandler.getNodeByIp(session, ip)

            return Node.getFromDbDict(node.__dict__)
        except TortugaException as ex:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
        finally:
            DbManager().closeSession()
Example #10
0
    def getNodeList(self, softwareProfileName):
        """
        Return list of nodes contained within specified software profile
        """

        url = 'v1/softwareProfiles/%s/nodes' % (
            urllib.parse.quote_plus(softwareProfileName))

        try:
            _, responseDict = self.sendSessionRequest(url)

            return Node.getListFromDict(responseDict)
        except TortugaException as ex:
            raise
        except Exception as ex:
            raise TortugaException(exception=ex)
Example #11
0
    def getNodeById(self,
                    nodeId: int,
                    optionDict: Optional[Union[dict, None]] = None):

        session = DbManager().openSession()

        try:
            dbNode = self._nodesDbHandler.getNodeById(session, nodeId)

            self.loadRelations(dbNode, optionDict)

            return Node.getFromDbDict(dbNode.__dict__)
        except TortugaException as ex:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
        finally:
            DbManager().closeSession()
Example #12
0
    def __convert_nodes_to_TortugaObjectList(
            self,
            nodes,
            relations: Optional[Union[dict,
                                      None]] = None) -> TortugaObjectList:
        nodeList = TortugaObjectList()

        relations = relations or dict(softwareprofile=True,
                                      hardwareprofile=True)

        for t in nodes:
            self.loadRelations(t, relations)

            # Always load 'tags' relation
            self.loadRelations(t, {'tags': True})

            node = Node.getFromDbDict(t.__dict__)

            nodeList.append(node)

        return nodeList
Example #13
0
def test_get_from_dict():
    d = {
        'id': 9999,
        'name': 'nodename',
        'hardwareprofile': {
            'name': 'LocalIron',
        },
        'softwareprofile': {
            'name': 'Compute',
        }
    }

    tmpnode = Node.getFromDict(d)

    assert tmpnode.getId() == 9999

    assert tmpnode.getName() == 'nodename'

    assert tmpnode.getHardwareProfile().getName() == 'LocalIron'

    assert tmpnode.getSoftwareProfile().getName() == 'Compute'
Example #14
0
    def getProvisioningInfo(self, nodeName):
        """
        Get the provisioing information for a given provisioned address

            Returns:
                [provisioningInformation structure]
            Throws:
                NodeNotFound
                DbError
        """

        session = DbManager().openSession()

        try:
            provisioningInfo = ProvisioningInfo()

            dbNode = self._nodesDbHandler.getNode(session, nodeName)

            if dbNode.softwareprofile:
                self.loadRelations(dbNode.softwareprofile, {
                    'partitions': True,
                    'packages': True,
                })

                for component in dbNode.softwareprofile.components:
                    self.loadRelations(
                        component, {
                            'kit': True,
                            'os': True,
                            'family': True,
                            'os_components': True,
                            'osfamily_components': True,
                        })

            self.loadRelation(dbNode, 'hardwareprofile')

            provisioningInfo.setNode(Node.getFromDbDict(dbNode.__dict__))

            globalParameters = self._globalParameterDbApi.getParameterList()

            # TODO: this is a terrible hack until something better comes
            # along.

            p = Parameter()
            p.setName('Installer')

            hostName = socket.gethostname().split('.', 1)[0]

            if '.' in dbNode.name:
                nodeDomain = dbNode.name.split('.', 1)[1]

                priInstaller = hostName + '.%s' % (nodeDomain)
            else:
                priInstaller = hostName

            p.setValue(priInstaller)

            globalParameters.append(p)

            provisioningInfo.setGlobalParameters(globalParameters)

            return provisioningInfo
        except TortugaException as ex:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
        finally:
            DbManager().closeSession()
Example #15
0
    def getProvisioningInfo(self, session: Session, nodeName: str) \
            -> ProvisioningInfo:
        """
        Get the provisioing information for a given provisioned address

            Returns:
                [provisioningInformation structure]
            Throws:
                NodeNotFound
                DbError
        """

        try:
            provisioningInfo = ProvisioningInfo()

            dbNode = self._nodesDbHandler.getNode(session, nodeName)

            if dbNode.softwareprofile:
                self.loadRelations(dbNode.softwareprofile, {
                    'partitions': True,
                })

                for component in dbNode.softwareprofile.components:
                    self.loadRelations(component, {
                        'kit': True,
                        'os': True,
                        'family': True,
                        'os_components': True,
                        'osfamily_components': True,
                    })

            self.loadRelation(dbNode, 'hardwareprofile')

            provisioningInfo.setNode(
                Node.getFromDbDict(dbNode.__dict__))

            globalParameters = \
                self._globalParameterDbApi.getParameterList(session)

            # manually inject value for 'installer'
            p = Parameter(name='Installer')

            hostName = getfqdn().split('.', 1)[0]

            if '.' in dbNode.name:
                nodeDomain = dbNode.name.split('.', 1)[1]

                priInstaller = hostName + '.%s' % (nodeDomain)
            else:
                priInstaller = hostName

            p.setValue(priInstaller)

            globalParameters.append(p)

            provisioningInfo.setGlobalParameters(globalParameters)

            return provisioningInfo
        except TortugaException:
            raise
        except Exception as ex:
            self.getLogger().exception('%s' % ex)
            raise
Example #16
0
def test_node_setBootFrom():
    with pytest.raises(ValueError):
        Node(name='mike').setBootFrom('mmmm')
Example #17
0
    def __delete_node(self, session: Session, dbNodes: List[NodeModel]) \
            -> Dict[str, List[NodeModel]]:
        """
        Raises:
            DeleteNodeFailed
        """

        result: Dict[str, list] = {
            'NodesDeleted': [],
            'DeleteNodeFailed': [],
            'SoftwareProfileLocked': [],
            'SoftwareProfileHardLocked': [],
        }

        nodes: Dict[HardwareProfileModel, List[NodeModel]] = {}
        events_to_fire: List[dict] = []

        #
        # Mark node states as deleted in the database
        #
        for dbNode in dbNodes:
            #
            # Capture previous state and node data as a dict for firing
            # the event later on
            #
            event_data = {
                'previous_state': dbNode.state,
                'node': Node.getFromDbDict(dbNode.__dict__).getCleanDict()
            }

            dbNode.state = state.NODE_STATE_DELETED
            event_data['node']['state'] = 'Deleted'

            if dbNode.hardwareprofile not in nodes:
                nodes[dbNode.hardwareprofile] = [dbNode]
            else:
                nodes[dbNode.hardwareprofile].append(dbNode)

        session.commit()

        #
        # Fire node state change events
        #
        for event in events_to_fire:
            NodeStateChanged.fire(node=event['node'],
                                  previous_state=event['previous_state'])

        #
        # Call resource adapter with batch(es) of node lists keyed on
        # hardware profile.
        #
        for hwprofile, hwprofile_nodes in nodes.items():
            # Get the ResourceAdapter
            adapter = self.__get_resource_adapter(session, hwprofile)

            # Call the resource adapter
            adapter.deleteNode(hwprofile_nodes)

            # Iterate over all nodes in hardware profile, completing the
            # delete operation.
            for dbNode in hwprofile_nodes:
                for tag in dbNode.tags:
                    if len(tag.nodes) == 1 and \
                            not tag.softwareprofiles and \
                            not tag.hardwareprofiles:
                        session.delete(tag)

                # Delete the Node
                self._logger.debug('Deleting node [%s]' % (dbNode.name))

                session.delete(dbNode)

                result['NodesDeleted'].append(dbNode)

        return result
Example #18
0
    def updateNodeStatus(self,
                         session: Session,
                         nodeName: str,
                         node_state: Optional[str] = None,
                         bootFrom: int = None):
        """Update node status

        If neither 'state' nor 'bootFrom' are not None, this operation will
        update only the 'lastUpdated' timestamp.

        Returns:
            bool indicating whether state and/or bootFrom differed from
            current value
        """

        value = 'None' if bootFrom is None else \
            '1 (disk)' if int(bootFrom) == 1 else '0 (network)'

        self._logger.debug(
            'updateNodeStatus(): node=[%s], node_state=[{%s}],'
            ' bootFrom=[{%s}]', nodeName, node_state, value)

        dbNode = self._nodesDbHandler.getNode(session, nodeName)

        #
        # Capture previous state and node data in dict form for the
        # event later on
        #
        previous_state = dbNode.state
        node_dict = Node.getFromDbDict(dbNode.__dict__).getCleanDict()

        # Bitfield representing node changes (0 = state change,
        # 1 = bootFrom # change)
        changed = 0

        if node_state is not None and node_state != dbNode.state:
            # 'state' changed
            changed |= 1

        if bootFrom is not None and bootFrom != dbNode.bootFrom:
            # 'bootFrom' changed
            changed |= 2

        if changed:
            # Create custom log message
            msg = 'Node [%s] state change:' % (dbNode.name)

            if changed & 1:
                msg += ' state: [%s] -> [%s]' % (dbNode.state, node_state)

                dbNode.state = node_state
                node_dict['state'] = node_state

            if changed & 2:
                msg += ' bootFrom: [%d] -> [%d]' % (dbNode.bootFrom, bootFrom)

                dbNode.bootFrom = bootFrom

            self._logger.info(msg)
        else:
            self._logger.info('Updated timestamp for node [%s]' %
                              (dbNode.name))

        dbNode.lastUpdate = time.strftime('%Y-%m-%d %H:%M:%S',
                                          time.localtime(time.time()))

        result = bool(changed)

        # Only change local boot configuration if the hardware profile is
        # not marked as 'remote' and we're not acting on the installer
        # node.
        if dbNode.softwareprofile and \
                dbNode.softwareprofile.type != 'installer' and \
                dbNode.hardwareprofile.location != 'remote':
            # update local boot configuration for on-premise nodes
            self._bhm.writePXEFile(session, dbNode, localboot=bootFrom)

        session.commit()

        #
        # If the node state has changed, fire the node state changed
        # event
        #
        if state and (previous_state != state):
            NodeStateChanged.fire(node=node_dict,
                                  previous_state=previous_state)

        return result
Example #19
0
def node():
    tmpnode = Node('testnode')
    tmpnode.setId(1234)

    return tmpnode
Example #20
0
def test_empty_node():
    assert not Node().getName()
Example #21
0
def test_node_getXmlRep(node):
    xmlstr = node.getXmlRep()

    tmpnode = Node.getFromXml(xmlstr)

    assert tmpnode.getName() == 'testnode'
Example #22
0
def test_node_getFromXml():
    xmlstr = '<node name="mike"/>'

    tmpnode = Node.getFromXml(xmlstr)

    assert tmpnode.getName() == 'mike'
Example #23
0
    def updateNode(self, session: Session, nodeName: str,
                   updateNodeRequest: dict) -> None:
        """
        Calls updateNode() method of resource adapter
        """

        self._logger.debug('updateNode(): name=[{0}]'.format(nodeName))

        try:
            node = self._nodesDbHandler.getNode(session, nodeName)

            if 'nics' in updateNodeRequest:
                nic = updateNodeRequest['nics'][0]

                if 'ip' in nic:
                    node.nics[0].ip = nic['ip']
                    node.nics[0].boot = True

            # Call resource adapter
            # self._nodesDbHandler.updateNode(session, node, updateNodeRequest)

            adapter = self.__getResourceAdapter(node.hardwareprofile)

            adapter.updateNode(session, node, updateNodeRequest)

            run_post_install = False

            #
            # Capture previous state and node data as dict for firing the
            # event later on
            #
            previous_state = node.state
            node_dict = Node.getFromDbDict(node.__dict__).getCleanDict()

            if 'state' in updateNodeRequest:
                run_post_install = \
                    node.state == state.NODE_STATE_ALLOCATED and \
                    updateNodeRequest['state'] == state.NODE_STATE_PROVISIONED

                node.state = updateNodeRequest['state']
                node_dict['state'] = updateNodeRequest['state']

            session.commit()

            #
            # If the node state has changed, then fire the node state changed
            # event
            #
            if node_dict['state'] != previous_state:
                NodeStateChanged.fire(node=node_dict,
                                      previous_state=previous_state)

            if run_post_install:
                self._logger.debug(
                    'updateNode(): run-post-install for node [{0}]'.format(
                        node.name))

                self.__scheduleUpdate()
        except Exception:
            session.rollback()

            raise
Example #24
0
    def createNewNode(self,
                      session: Session,
                      addNodeRequest: dict,
                      dbHardwareProfile: HardwareProfileModel,
                      dbSoftwareProfile: Optional[SoftwareProfileModel] = None,
                      validateIp: bool = True,
                      bGenerateIp: bool = True,
                      dns_zone: Optional[str] = None) -> NodeModel:
        """
        Convert the addNodeRequest into a Nodes object

        Raises:
            NicNotFound
        """

        self._logger.debug(
            'createNewNode(): session=[%s], addNodeRequest=[%s],'
            ' dbHardwareProfile=[%s], dbSoftwareProfile=[%s],'
            ' validateIp=[%s], bGenerateIp=[%s]' %
            (id(session), addNodeRequest, dbHardwareProfile.name,
             dbSoftwareProfile.name if dbSoftwareProfile else '(none)',
             validateIp, bGenerateIp))

        hostname = addNodeRequest['name'] \
            if 'name' in addNodeRequest else None

        # Ensure no conflicting options (ie. specifying host name for
        # hardware profile in which host names are generated)
        self.__validateHostName(hostname, dbHardwareProfile.nameFormat)

        node: Node = NodeModel(name=hostname)

        if 'rack' in addNodeRequest:
            node.rack = addNodeRequest['rack']

        node.addHostSession = addNodeRequest['addHostSession']

        # Complete initialization of new node record
        nic_defs = addNodeRequest['nics'] \
            if 'nics' in addNodeRequest else []

        AddHostServerLocal().initializeNode(session,
                                            node,
                                            dbHardwareProfile,
                                            dbSoftwareProfile,
                                            nic_defs,
                                            bValidateIp=validateIp,
                                            bGenerateIp=bGenerateIp,
                                            dns_zone=dns_zone)

        node.hardwareprofile = dbHardwareProfile
        node.softwareprofile = dbSoftwareProfile

        #
        # Fire the tags changed event for all creates that have tags...
        # we have to convert this to a node object because... our API
        # is inconsistent!
        #
        n = Node.getFromDbDict(node.__dict__)
        if n.getTags():
            NodeTagsChanged.fire(node=n.getCleanDict(), previous_tags={})

        # Return the new node
        return node