Пример #1
0
    def show_real_disabled(self, host, port, numeric):
        """show status of disabled real server across multiple VIPs"""

        logger.debug("Keepalived.show_real_disabled(): host:%s" % host)
        logger.debug("Keepalived.show_real_disabled(): port:%s" % port)
        output = list()

        # update the ipvs table
        self.build_ipvs()
        for i, v in enumerate(self.virtuals):
            for j, r in enumerate(v.realServers):
                if r.weight == "0":
                    h = utils.gethostbyname_ex(host)
                    # if user enters an invalid hostname, just return
                    if not h:
                        return ''
                    if not host or h[0] == r.ip:
                        if not port or utils.getportnum(port) == r.port:
                            if numeric:
                                output.append("%s:%s" % (r.ip, r.port))
                            else:
                                host, aliaslist, ipaddrlist = socket.gethostbyaddr(
                                    r.ip)
                                portname = socket.getservbyport(int(r.port))
                                output.append("%s:%s" % (host, portname))

                            try:
                                filename = "%s/realServerReason.%d.%d" % (
                                    self.cache_dir, i + 1, j + 1)
                                f = open(filename)
                                reason = 'Reason: ' + f.readline()
                                logger.debug(
                                    "Keepalived.show_real_disabled(): %s" %
                                    reason)
                                f.close()
                            except IOError as e:
                                logger.error(e)
                                reason = ''

                            output[-1] = output[-1] + "\t\t" + reason
        return output
Пример #2
0
    def show_real_disabled(self, host, port, numeric):
        """show status of disabled real server across multiple VIPs"""

        logger.debug("Keepalived.show_real_disabled(): host:%s" % host)
        logger.debug("Keepalived.show_real_disabled(): port:%s" % port)
        output = list()

        # update the ipvs table
        self.build_ipvs()
        for i, v in enumerate(self.virtuals):
            for j, r in enumerate(v.realServers):
                if r.weight == "0": 
                    if not host or utils.gethostbyname_ex(host)[0] == r.ip:
                        if not port or utils.getportnum(port) == r.port:
                            if numeric:
                                output.append("%s:%s" % (r.ip, r.port))
                            else: 
                                try:
                                    host, aliaslist, ipaddrlist = socket.gethostbyaddr(r.ip)
                                except socket.herror as e:
                                    host = r.ip 
                                try:
                                    portname = socket.getservbyport(int(r.port))
                                except socket.error as e:
                                    portname = r.port
                                output.append("%s:%s" % (host, portname))
                            
                            try:
                                filename = "%s/realServerReason.%d.%d" % (self.cache_dir, i+1, j+1)
                                f = open(filename)
                                reason = 'Reason: ' + f.readline()
                                logger.debug("Keepalived.show_real_disabled(): %s" % reason)
                                f.close()
                            except IOError as e:
                                logger.error(e)
                                reason = ''

                            output[-1] = output[-1] + "\t\t" + reason
        return output
Пример #3
0
    def disable(self, protocol, host, port='', vhost='', vport='', reason=''):
        """
        Disable a real server in keepalived. This command rellies on snimpy
        and will set the weight of the real server to 0.
        The reason is not used in this case.
        """
        found = False

        hostips = utils.gethostbyname_ex(host)
        if not hostips:
            logger.error('Real server %s is not valid!' % host)
            return False

        # Here we only use the first IP if the host has more than one
        hostip = hostips[0]
        if port:
            # check that it's a valid port
            portnum = utils.getportnum(port)
            if portnum == -1:
                logger.error('Port %s is not valid!' % port)
                return False
        
        if vhost:
            vipnums = utils.gethostbyname_ex(vhost)
            if not vipnums:
                logger.error('Virtual host %s not valid!' % vhost)
                return False

            # only take the first ip address if host has more than one
            vipnum = vipnums[0]

        if vport:
            vportnum = utils.getportnum(vport)
            if vportnum == -1:
                logger.error('Virtual port %s is not valid!' % vport)
                return False
        
        try:
            manager.load(self.mib)
            m = manager.Manager(self.snmp_host, self.snmp_community)
                                # Not compatible with earlier 
                                # versions of snimpy
                                #secname=self.snmp_user,
                                #authpassword=self.snmp_password)
        except (snmp.SNMPException, mib.SMIException) as e:
            logger.error(e)
            logger.error("Unable to perfrom action!")
            return False

        # iterate through the virtual servers
        # and disable the matching real server
        try:
            for i in m.virtualServerAddress:
                hexip = m.virtualServerAddress[i]
                vip = socket.inet_ntoa(hexip)
                logger.debug("Keepalived.disable(): Checking VIP: %s" % vip)
                logger.debug("Keepalived.disable(): Protocol: %s" % str(m.virtualServerProtocol[i]))
                if m.virtualServerProtocol[i] == protocol:
                    if not vhost or vipnum == vip:
                        vp = m.virtualServerPort[i]
                        if not vport or vportnum == vp:
                            # iterate over the realservers in 
                            # the specific virtual
                            j = m.virtualServerRealServersTotal[i]
                            idx = 1                    
                            while idx <= j:
                                hexip = m.realServerAddress[i,idx]
                                rip = socket.inet_ntoa(hexip)
                                rp = m.realServerPort[i,idx]
                                if hostip == rip:                                                        
                                    if not port or (port and portnum == rp):
                                        logger.debug('Keepalived.disable(): Disabling %s:%s on VIP %s:%s' % (rip, rp, vip, vp))
                                        # 'found' is used to keep track of
                                        # matching real servers to disable
                                        found = True

                                        # Record the original weight
                                        # before disabling it
                                        # It'll be used when enabling 
                                        weight = m.realServerWeight[i,idx]
                                        logger.debug('Keepalived.disable(): Current weight: %s' % weight)

                                        if weight == 0:
                                            logger.warning("Real server %s:%s is already disabled on VIP %s:%s" % (rip, rp, vip, vp))
                                            idx += 1
                                            continue

                                        filename = "realServerWeight.%s.%s" % (i, idx)
                                        fullpath = '%s/%s' % (self.cache_dir, filename)
                                        rfilename = "realServerReason.%s.%s" % (i, idx)
                                        rfullpath = '%s/%s' % (self.cache_dir, rfilename)
                                        try:
                                            # Create a file with the original weight 
                                            logger.info('Creating file: %s' % fullpath)
                                            f = open(fullpath, 'w')
                                            f.write(str(weight))
                                            f.close()

                                            # Create a file with the disable reason
                                            logger.info('Creating file: %s' % rfullpath)
                                            f = open(rfullpath, 'w')
                                            f.write(str(reason))
                                            f.close()
                                        except IOError as e:
                                            logger.error(e)
                                            logger.error('Please make sure %s is writable before proceeding!' % self.cache_dir)
                                            return False 

                                        # Copy the file to the other nodes
                                        # In case of a switch lvsm will have 
                                        # the weight info on all nodes
                                        self.filesync_nodes('copy', fullpath)
                            
                                        # set the weight to zero
                                        community = "private"
                                        cmd_example = "snmpset -v2c -c %s localhost KEEPALIVED-MIB::%s = 0" % (community, filename)
                                        logger.info("Running equivalent command to: %s" % cmd_example)
                                        m.realServerWeight[i,idx] = 0
                                        print "Disabled %s:%s on VIP %s:%s (%s). Weight set to 0." % (rip, rp, vip, vp, protocol)
                                idx += 1
        except snmp.SNMPException as e:
            logger.error(e)
            logger.error("Unable to complete the command successfully! Please verify manually.")
            return False 

        if not found:
            logger.error('No matching real servers were found!')
            return False
        else:
            return True
Пример #4
0
    def enable(self, protocol, rhost, rport='',vhost='', vport=''):
        """
        Enable a real server in keepalived. This command rellies on snimpy
        and will set the weight of the real server back to its original weight. 
        Assumption: original weight is stored in self.cache_dir/realServerWeight.x.y
        The reason is not used in this case.
        """

        hostips = utils.gethostbyname_ex(rhost)
        if not hostips:
            logger.error('Real server %s is not valid!' % rhost)
            return False

        # Here we only use the first IP if the host has more than one
        hostip = hostips[0]

        if rport:
            # check that it's a valid port
            portnum = utils.getportnum(rport)
            if portnum == -1:
                logger.error('Port %s is not valid!' % rport)
                return False
        
        if vhost:
            vipnum = utils.gethostname(vhost)
            if not vipnum:
                logger.error('Virtual host %s not valid!' % vhost)
                return False

        if vport:
            vportnum = utils.getportnum(vport)
            if vportnum == -1:
                logger.error('Virtual port %s is not valid!' % vport)
                return False
        
        try:
            manager.load(self.mib)
            m = manager.Manager(self.snmp_host, self.snmp_community)
                                # Not compatible with earlier 
                                # versions of snimpy
                                # secname=self.snmp_user,
                                # authpassword=self.snmp_password)
        except (snmp.SNMPException, mib.SMIException) as e:
            logger.error(e)
            logger.error("Unable to perfrom action!")
            return False

        # iterate through the virtual servers
        # and enable the matching real server
        # if the weight is zero.
        # Note: if file is not found in the cache_dir (i.e. /var/cache/lvsm)
        # we set the weight 1 (keepalived default)
        try:
            for i in m.virtualServerAddress:
                hexip = m.virtualServerAddress[i]
                vip = socket.inet_ntoa(hexip)
                logger.debug("Keepalived.enable(): Checking VIP: %s" % vip)
                logger.debug("Keepalived.enable(): Protocol: %s" % str(m.virtualServerProtocol[i]))
                if m.virtualServerProtocol[i] == protocol:
                    if not vhost or vipnum == vip:
                        vp = m.virtualServerPort[i]
                        if not vport or vportnum == vp:
                            # iterate over the realservers in 
                            # the specific virtual host
                            j = m.virtualServerRealServersTotal[i]
                            idx = 1
                            while idx <= j:
                                hexip = m.realServerAddress[i,idx]
                                rip = socket.inet_ntoa(hexip)
                                logger.debug("Keepalived.enable(): RIP: %s" % rip)
                                rp = m.realServerPort[i,idx]
                                if hostip == rip:
                                    if not rport or (rport and portnum == rp):
                                        # Record the original weight somewhere before disabling it
                                        # Will be used when enabling the server
                                        weight = m.realServerWeight[i,idx]
                                        logger.debug('Keepalived.enable(): Current weight: %s' % weight)
                                        if weight > 0:
                                            msg = "Real server %s:%s on VIP %s:%s is already enabled with a weight of %s" % (rip, rp, vip, vp, weight)
                                            logger.warning(msg)
                                            idx += 1 
                                            continue

                                        filename = "realServerWeight.%s.%s" % (i, idx)
                                        fullpath = '%s/%s' % (self.cache_dir, filename)

                                        logger.debug('Keepalived.enable(): Enabling %s:%s on VIP %s:%s' % (rip, rp, vip, vp))
                                        try:
                                            logger.debug('Keepalived.enable(): Reading server weight from file: %s' % fullpath)
                                            f = open(fullpath, 'r')
                                            str_weight = f.readline().rstrip()
                                            f.close()
                                            # make sure the weight is a valid int 
                                            orig_weight = int(str_weight) 
                                        except IOError as e:
                                            logger.warning("%s. Using 1 as default weight!" % e)
                                            logger.warning("To ensure the correct wieght is set, please restart Keepalived.")
                                            orig_weight = 1
                                       
                                        # set the weight to zero
                                        community = "private"
                                        cmd_example = "snmpset -v2c -c %s localhost KEEPALIVED-MIB::%s = %s" % (community, filename, orig_weight)
                                        logger.info("Running equivalent command to: %s" % cmd_example)
                                        m.realServerWeight[i,idx] = orig_weight
                                        print "Enabled %s:%s on VIP %s:%s (%s). Weight set to %s." % (rip, rp, vip, vp, protocol, orig_weight)

                                        # Now remove the placeholder file locally
                                        try:
                                            logger.debug("Keeplived.enable(): removing placehodler file")
                                            os.unlink(fullpath)
                                        except OSError as e:
                                            logger.error(e)
                                            logger.error('Please make sure %s is writable!' % self.cache_dir)
                                            logger.error('%s needs to be manually deleted to avoid future problems.' % fullpath)

                                        # Try removing the reason file
                                        rfilename = "realServerReason.%s.%s" % (i, idx)
                                        rfullpath = '%s/%s' % (self.cache_dir, rfilename)
                                        try:
                                            logger.debug("Keeplived.enable(): removing reason file")
                                            os.unlink(rfullpath)
                                        except OSError as e:
                                            logger.error(e)
                                            logger.error('Please make sure %s is writable!' % self.cache_dir)
                                            logger.error('%s needs to be manually deleted to avoid future problems.' % rfullpath)


                                        # remove the placeholder file in other nodes
                                        self.filesync_nodes('remove', fullpath)

                                idx += 1
        except snmp.SNMPException as e:
            logger.error(e)
            logger.error("Unable to complete the command successfully! Please verify manually.")
            return False 

        return True
Пример #5
0
    def disable(self, host, port='', reason=''):
        # Prepare a canned error message
        error_msg = "Problem disabling on remote node"
        if self.maintenance_dir:
            hostips = utils.gethostbyname_ex(host)
            if not hostips:
                return False

            # In disable cmd, we ignore if the host has more than one IP
            hostip = hostips[0]

            if port:
                # check that it's a valid port
                portnum = utils.getportnum(port)
                if portnum == -1:
                    return False
                hostport = hostip + ":" + str(portnum)
            else:
                hostport = hostip
            # go through maint_dir to see if host is already disabled
            filenames = os.listdir(self.maintenance_dir)
            for filename in filenames:
                f = self.convert_filename(filename)
                if hostport == f or hostip == f:
                    logger.warning("host is already disabled!")
                    return True
            try:
                f = open(self.maintenance_dir + "/" + hostport, 'w')
                f.write(reason)
            except IOError as e:
                logger.error(e)
                return False

            # Copy the state file to other nodes
            fullpath = self.maintenance_dir + "/" + hostport
            self.filesync_nodes('copy', fullpath)

            # Confirm that it's removed from ldirector
            i = 0
            print "Disabling server ",
            while i < 10:
                sys.stdout.write(".")
                sys.stdout.flush()
                time.sleep(1)
                i = i + 1
                found = False

                output = self.show_running(numeric=True, color=False)
                for line in output:
                    if hostport in line:
                        found = True
                        break
                if not found:
                    print " OK"
                    break
            if found:
                print " Failed"
            # note: even if the real is still showing up, we've created
            # the file, so we should still return true
            return True
        else:
            logger.error("maintenance_dir not defined in config.")
            return False
Пример #6
0
    def show_real_disabled(self, host, port, numeric):
        """show status of disabled real server across multiple VIPs"""
        # note that host='' and port='' returns all disabled server
        hostip = ''
        hostport = ''
        if host:
            hostips = utils.gethostbyname_ex(host)
            if not hostips:
                return

            # Here we only use the first IP if a host has more than one
            hostip = hostips[0]

            if port:
                portnum = utils.getportnum(port)
                if portnum == -1:
                    return
                hostport = hostip + ":" + str(portnum)

        output = list()

        if not self.maintenance_dir:
            logger.error("maintenance_dir not defined!")
            return output

        # make sure to catch errors like related to maint_dir
        try:
            filenames = os.listdir(self.maintenance_dir)
        except (IOError, OSError) as e:
            logger.error("Config item maintenance_dir")
            logger.error(e)
            return output

        for filename in filenames:
            try:
                f = open(self.maintenance_dir + "/" + filename)
                reason = 'Reason: ' + f.readline()
                f.close()
            except IOError as e:
                reason = ''
                logger.error(e)
            if (not host or self.convert_filename(filename) == hostip
                    or self.convert_filename(filename) == hostport):

                # decide if we have to convert to hostname or not
                if numeric:
                    output.append(filename + "\t\t" + reason)
                else:
                    rip = filename.split(":")[0]
                    try:
                        (ripname, al, ipl) = socket.gethostbyaddr(rip)
                    except socket.herror, e:
                        logger.error(e)
                        return False
                    if len(filename.split(":")) == 2:
                        ripport = filename.split(":")[1]
                        try:
                            ripportname = socket.getservbyport(int(ripport))
                        except socket.error as e:
                            ripportname = ripport
                        ripname = ripname + ':' + ripportname
                    else:
                        pass
                    output.append(ripname + "\t\t" + reason)
Пример #7
0
    def enable(self, host, port=''):
        """enable a previously disabled server"""
        # Prepare a canned error message.
        error_msg = "Problem enabling on remote node"

        hostips = utils.gethostbyname_ex(host)
        if not hostips:
            return False

        # In enable cmd, we ignore if the host has more than one IP
        hostip = hostips[0]

        # If port was provided the file will be of form xx.xx.xx.xx:nn
        if port:
            # Check that the port is valid.
            portnum = utils.getportnum(port)
            if portnum == -1:
                return False
            hostport = hostip + ":" + str(portnum)
        # If no port was provided the file be of form xx.xx.xx.xx
        else:
            hostport = hostip
        if self.maintenance_dir:
            filenames = os.listdir(self.maintenance_dir)
            # Go through all files in maintenance_dir
            # and find a matching filename, and remove it.
            for filename in filenames:
                f = self.convert_filename(filename)
                # If user asks to enable xx.xx.xx.xx and xx.xx.xx.xx:nn
                # is disabled, we enable all ports and remove all the files.
                if (hostport == f or (not port and hostip in f)):
                    try:
                        os.unlink(self.maintenance_dir + "/" + filename)
                    except OSError as e:
                        logger.error(e)
                        return False

                    # Remove the same file from other nodes in the cluster.
                    fullpath = self.maintenance_dir + "/" + filename
                    self.filesync_nodes('remove', fullpath)

                    # Wait 4.5 seconds before checking output of ipvsadm.
                    # This is an arbitrary number and could possibly be changed
                    i = 0
                    print "Enabling server ",
                    while i < 10:
                        sys.stdout.write(".")
                        sys.stdout.flush()
                        time.sleep(1)
                        i = i + 1

                        # Verify that the host is active in ldirectord.
                        output = self.show_running(numeric=True, color=False)
                        for line in output:
                            if hostport in line:
                                print " OK"
                                return True
                    # If we get to this point, means the host is not active.
                    print " Failed"
                    # Note: even if the real isn't showing up, we have removed
                    # the file, so we should still return true.
                    return True
            # If we make it out here means the real wasn't in the file list.
            logger.error("Server not found in maintenance_dir!")
            return False
        else:
            logger.error("maintenance_dir not defined!")
            return False