Пример #1
0
// ensureInterHostRoutes ensures we have routes to every other host.
func (h Helper) ensureInterHostRoutes() error {
	log.Trace(trace.Inside, "Acquiring mutex ensureInterhostRoutes")
	h.ensureInterHostRoutesMutex.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing mutex ensureInterhostRoutes")
		h.ensureInterHostRoutesMutex.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired mutex ensureInterhostRoutes")

	via := "via"
	log.Tracef(trace.Inside, "In ensureInterHostRoutes over %v\n", h.Agent.networkConfig.otherHosts)
	for _, host := range h.Agent.networkConfig.otherHosts {
		log.Tracef(trace.Inside, "In ensureInterHostRoutes ensuring route for %v\n", host)
		_, romanaCidr, err := net.ParseCIDR(host.RomanaIp)
		if err != nil {
			return failedToParseOtherHosts(host.RomanaIp)
		}
		romanaMaskInt, _ := romanaCidr.Mask.Size()
		romanaMask := fmt.Sprintf("%d", romanaMaskInt)
		dest := host.Ip

		// wait until no one messing with routes
		// If route doesn't exist yet
		if err := h.isRouteExist(romanaCidr.IP, romanaMask); err != nil {

			// Create it
			err2 := h.createRoute(romanaCidr.IP, romanaMask, via, dest)
			if err2 != nil {
				return routeCreateError(err, romanaCidr.IP.String(), romanaMask, dest)
			}
		}
	}
	return nil
}
Пример #2
0
// rootState is a state at the beginning of the input and outside of any other state.
func rootState(l *Lexer) stateFn {
	log.Trace(trace.Private, "In root state")
	for {
		b := l.nextByte()

		// There are 5 states we can go from root.
		switch string(b) {
		case string(endOfText):
			return l.errorEof("EOF reached in root section")
		case "#":
			log.Trace(trace.Inside, "In root state, switching into the comment state")
			return stateInComment
		case "*":
			log.Trace(trace.Inside, "In root state, switching into the table state")
			return stateInTable
		case ":":
			log.Trace(trace.Inside, "In root state, switching into the chain state")
			return stateInChain
		case "-":
			// Checking one byte ahead of reader to detect "-A"
			if l.accept("A ") {
				log.Trace(trace.Inside, "In root state, switching into the rule state")
				return stateInRule
			}
		case "C":
			// Whenever we arrive at "C" we need to check if it is a "COMMIT" token.
			if l.accept("OMMIT\n") {
				l.items <- Item{Type: itemCommit, Body: "COMMIT"}
				return rootState
			}
		}
	}
}
Пример #3
0
// lastTable returns pointer to the last IPtable in IPtables.
func (i *IPtables) lastTable() *IPtable {
	log.Trace(trace.Private, "In lastTable()")
	if len(i.Tables) == 0 {
		return nil
	}

	t := i.Tables[len(i.Tables)-1]
	log.Trace(trace.Inside, "In lastTable returning with ", t.Name)
	return t
}
Пример #4
0
// SetConfig implements SetConfig function of the Service interface.
func (a *Agent) SetConfig(config common.ServiceConfig) error {
	log.Trace(trace.Public, config)
	a.config = config
	leaseFileName := config.ServiceSpecific["lease_file"].(string)
	lf := NewLeaseFile(leaseFileName, a)
	a.leaseFile = &lf

	a.waitForIfaceTry = int(config.ServiceSpecific["wait_for_iface_try"].(float64))
	a.networkConfig = &NetworkConfig{}

	a.store = *NewStore(config)

	log.Trace(trace.Inside, "Agent.SetConfig() finished.")
	return nil
}
Пример #5
0
// podDownHandler cleans up after pod deleted.
func (a *Agent) podDownHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	log.Trace(trace.Private, "Agent: Entering podDownHandler()")
	netReq := input.(*NetworkRequest)
	netif := netReq.NetIf

	// We need new firewall instance here to use its Cleanup()
	// to uninstall firewall rules related to the endpoint.
	fw, err := firewall.NewFirewall(a.getFirewallType())
	if err != nil {
		return nil, err
	}

	err = fw.Init(a.Helper.Executor, a.store, a.networkConfig)
	if err != nil {
		return nil, err
	}

	err = fw.Cleanup(netif)
	if err != nil {
		return nil, err
	}

	// Spawn new thread to process the request
	log.Infof("Agent: Got request for pod teardown %v\n", netReq)

	return "OK", nil
}
Пример #6
0
// NextItem returns next item from input stream.
func (l *Lexer) NextItem() Item {
	log.Trace(trace.Public, "In NextItem()")
	for {
		select {
		case item := <-l.items:
			log.Trace(trace.Inside, "In NextItem() returning item ", item)
			return item
		default:
			if l.state == nil {
				panic("Lexer failed to process input stream")
			}

			log.Trace(trace.Inside, "In NextItem(), next state")
			l.state = l.state(l)
		}
	}
}
Пример #7
0
func (agentStore *agentStore) listRoutes() ([]Route, error) {
	log.Trace(trace.Inside, "Acquiring store mutex for listRoutes")
	agentStore.mu.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing store mutex for listRoutes")
		agentStore.mu.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired store mutex for listRoutes")

	var routes []Route
	agentStore.DbStore.Db.Find(&routes)
	err := common.MakeMultiError(agentStore.DbStore.Db.GetErrors())
	if err != nil {
		return nil, err
	}
	return routes, nil
}
Пример #8
0
// SetConfig implements SetConfig function of the Service interface.
func (l *KubeListener) SetConfig(config common.ServiceConfig) error {
	confString := "/etc/romana/romana.conf.yml:kubernetesListener:config:"
	log.Trace(trace.Inside, confString, config)

	m := config.ServiceSpecific
	if kl, ok := m["kubernetes_url"]; !ok || kl == "" {
		return fmt.Errorf("%s%s", confString, "kubernetes_url required in config.")
	}
	l.kubeURL = m["kubernetes_url"].(string)

	if nnp, ok := m["namespace_notification_path"]; !ok || nnp == "" {
		return fmt.Errorf("%s%s", confString, "namespace_notification_path required in config.")
	}
	l.namespaceNotificationPath = m["namespace_notification_path"].(string)

	if pnppre, ok := m["policy_notification_path_prefix"]; !ok || pnppre == "" {
		return fmt.Errorf("%s%s", confString, "policy_notification_path_prefix required in config.")
	}
	l.policyNotificationPathPrefix = m["policy_notification_path_prefix"].(string)

	if pnppost, ok := m["policy_notification_path_prefix"]; !ok || pnppost == "" {
		return fmt.Errorf("%s%s", confString, "policy_notification_path_postfix required in config.")
	}
	l.policyNotificationPathPostfix = m["policy_notification_path_postfix"].(string)

	if sln, ok := m["segment_label_name"]; !ok || sln == "" {
		return fmt.Errorf("%s%s", confString, "segment_label_name required in config.")
	}
	l.segmentLabelName = m["segment_label_name"].(string)

	if tln, ok := m["tenant_label_name"]; !ok || tln == "" {
		return fmt.Errorf("%s%s", confString, "tenant_label_name required in config.")
	}
	l.tenantLabelName = m["tenant_label_name"].(string)

	l.namespaceBufferSize = 1000

	if kc, ok := m["kubernetes_config"]; !ok || kc == "" {
		// Default kubernetes config location on ubuntu
		// TODO: this should not be hard coded, other
		//       distributions may have other user names.
		m["kubernetes_config"] = "/home/ubuntu/.kube/config"
	}

	// TODO, this loads kubernetes config from flags provided in main
	// should be loading from path provided by romana-root. Stas.
	kubeClientConfig, err := clientcmd.BuildConfigFromFlags("", m["kubernetes_config"].(string))
	if err != nil {
		return errors.New(fmt.Sprintf("Failed to load kubernetes kubeClientConfig %s", err))
	}
	clientset, err := kubernetes.NewForConfig(kubeClientConfig)
	if err != nil {
		return fmt.Errorf("Failed to make kubernetes client %s", err)
	}
	l.kubeClient = clientset

	return nil
}
Пример #9
0
// lastChain returns pointer to the last IPchain in IPtable.
func (i *IPtable) lastChain() *IPchain {
	log.Trace(trace.Private, "In lastChain()")
	if len(i.Chains) == 0 {
		return nil
	}

	c := i.Chains[len(i.Chains)-1]
	return c
}
Пример #10
0
// stateInComment consumes entire line.
func stateInComment(l *Lexer) stateFn {
	log.Trace(trace.Private, "In comment state")

	item := Item{Type: itemComment}
	for {
		b := l.nextByte()
		c := string(b)

		switch c {
		case string(endOfText):
			return l.errorf("Error: unexpected EOF in comment section")
		case "\n":
			l.items <- item
			log.Trace(trace.Inside, "In comment state, switching into the root state")
			return rootState
		default:
			item.Body += c
		}
	}
}
Пример #11
0
// createRoute creates IP route, returns nil if success and error otherwise.
func (h Helper) createRoute(ip net.IP, netmask string, via string, dest string, extraArgs ...string) error {
	log.Trace(trace.Private, "Helper: creating route")
	cmd := "/sbin/ip"
	targetIP := fmt.Sprintf("%s/%v", ip, netmask)
	args := []string{"ro", "add", targetIP, via, dest}
	args = append(args, extraArgs...)
	if _, err := h.Executor.Exec(cmd, args); err != nil {
		return shelloutError(err, cmd, args)
	}
	return nil // success
}
Пример #12
0
// getFirewallType converts configuration option firewall_provider into
// firewall.Provider type.
func (a Agent) getFirewallType() firewall.Provider {
	provider, ok := a.config.ServiceSpecific["firewall_provider"].(string)
	if !ok {
		panic("Unable to read firewall_provider from config")
	}

	// Value of "shellex" stands for firewall provider that executes iptables
	// commands line by line and value of "save-restore" stands for
	// firewall provider that uses iptables-save/iptables-restore.
	switch provider {
	case "shellex":
		log.Trace(trace.Inside, "Agent: using ShellexProvider firewall provider")
		return firewall.ShellexProvider
	case "save-restore":
		log.Trace(trace.Inside, "Agent: using IPTsaveProvider firewall provider")
		return firewall.IPTsaveProvider
	default:
		panic(fmt.Sprintf("Unsupported firewall type value %s, supported values are 'shellex' and 'save-restore'", provider))
	}

}
Пример #13
0
func (agentStore *agentStore) deleteRoute(route *Route) error {
	log.Trace(trace.Inside, "Acquiring store mutex for deleteRoute")
	agentStore.mu.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing store mutex for deleteRoute")
		agentStore.mu.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired store mutex for deleteRoute")

	db := agentStore.DbStore.Db
	agentStore.DbStore.Db.Delete(route)
	err := common.MakeMultiError(db.GetErrors())
	if err != nil {
		return err
	}
	if db.Error != nil {
		return db.Error
	}

	return nil
}
Пример #14
0
// ChainByName looks for IPchain with corresponding name and returns a pointer to it.
func (i *IPtable) ChainByName(name string) *IPchain {
	log.Trace(trace.Private, "In ChainByName()")

	for n, c := range i.Chains {
		if c.Name == name {
			ret := i.Chains[n]
			return ret
		}
	}

	return nil
}
Пример #15
0
func (agentStore *agentStore) findRouteByIface(routeIface string) (*Route, error) {
	log.Trace(trace.Inside, "Acquiring store mutex for findRoute")
	agentStore.mu.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing store mutex for findRoute")
		agentStore.mu.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired store mutex for findRoute")

	var route Route
	db := agentStore.DbStore.Db
	agentStore.DbStore.Db.Where("ip = ?", routeIface).First(&route)
	err := common.MakeMultiError(db.GetErrors())
	if err != nil {
		return nil, err
	}
	if db.Error != nil {
		return nil, db.Error
	}
	return &route, nil
}
Пример #16
0
// ensureLine ensures that line is present in a file.
func (h Helper) ensureLine(path string, token string, op leaseOp) error {
	// if file exist
	if err := h.OS.CreateIfMissing(path); err != nil {
		return ensureLineError(err)
	}

	// wait until no one using the file
	log.Trace(trace.Inside, "Acquiring mutex ensureLine")
	h.ensureLineMutex.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing mutex ensureLine")
		h.ensureLineMutex.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired mutex ensureLine")
	lineInFile, err := h.isLineInFile(path, token)
	if err != nil {
		return ensureLineError(err)
	}

	switch op {
	case leaseAdd:
		if !lineInFile {
			if err := h.appendLineToFile(path, token); err != nil {
				return ensureLineError(err)
			}
		} else {
			// nothing to do
		}
	case leaseRemove:
		if lineInFile {
			if err := h.removeLineFromFile(path, token); err != nil {
				return ensureLineError(err)
			}
		} else {
			// nothing to do
		}
	}
	return nil
}
Пример #17
0
// ensureRouteToEndpoint verifies that ip route to endpoint interface exists, creates it otherwise.
// Error if failed, nil if success.
func (h Helper) ensureRouteToEndpoint(netif *NetIf) error {
	mask := fmt.Sprintf("%d", h.Agent.networkConfig.EndpointNetmaskSize())
	log.Trace(trace.Private, "Ensuring routes for ", netif.IP, " ", netif.Name)
	log.Trace(trace.Inside, "Acquiring mutex ensureRouteToEndpoint")
	h.ensureRouteToEndpointMutex.Lock()
	defer func() {
		log.Trace(trace.Inside, "Releasing mutex ensureRouteToEndpoint")
		h.ensureRouteToEndpointMutex.Unlock()
	}()
	log.Trace(trace.Inside, "Acquired mutex ensureRouteToEndpoint")
	// If route not exist
	if err := h.isRouteExist(netif.IP.IP, mask); err != nil {

		// Create route
		via := "dev"
		dest := netif.Name

		err := h.createRoute(netif.IP.IP, mask, via, dest, "src", h.Agent.networkConfig.romanaGW.String())
		if err != nil {
			return netIfRouteCreateError(err, *netif)
		}
	}
	return nil
}
Пример #18
0
// podUpHandler handles HTTP requests for endpoints provisioning.
func (a *Agent) podUpHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	log.Trace(trace.Private, "Agent: Entering podUpHandler()")
	netReq := input.(*NetworkRequest)

	log.Infof("Agent: Got request for network configuration: %v\n", netReq)
	// Spawn new thread to process the request

	// TODO don't know if fork-bombs are possible in go but if they are this
	// need to be refactored as buffered channel with fixed pool of workers
	go a.podUpHandlerAsync(*netReq)

	// TODO I wonder if this should actually return something like a
	// link to a status of this request which will later get updated
	// with success or failure -- Greg.
	return "OK", nil
}
Пример #19
0
// stateInChainPolicy consumes chain deafult policy if any.
func stateInChainPolicy(l *Lexer) stateFn {
	log.Trace(trace.Private, "In chain policy state")

	item := Item{Type: itemChainPolicy}

	b := l.nextByte()
	c := string(b)

	switch c {
	case string(endOfText):
		return l.errorf("Error: unexpected EOF in chain section")
	case "-":
		item.Body = "-"
		l.items <- item
		_ = l.nextByte() // Discard next space to prevent it from getting captured as counter
		return stateInChainCounter
	case "A":
		if l.accept("CCEPT ") {
			item.Body = "ACCEPT"
			l.items <- item
			return stateInChainCounter
		} else {
			l.items <- Item{Type: ItemError, Body: "Unexpected deafult policy for a chain"}
			return nil
		}
	case "R":
		if l.accept("ETURN ") {
			item.Body = "RETURN"
			l.items <- item
			return stateInChainCounter
		} else {
			l.items <- Item{Type: ItemError, Body: "Unexpected deafult policy for a chain"}
			return nil
		}
	case "D":
		if l.accept("ROP ") {
			item.Body = "DROP"
			l.items <- item
			return stateInChainCounter
		} else {
			l.items <- Item{Type: ItemError, Body: "Unexpected deafult policy for a chain"}
			return nil
		}
	default:
		return l.errorf("Unexpectend end of line in chain state")
	}
}
Пример #20
0
// waitForIface waits for network interface to become available in the system.
func (h Helper) waitForIface(expectedIface string) bool {
	for i := 0; i <= h.Agent.waitForIfaceTry; i++ {
		log.Tracef(trace.Inside, "Helper: Waiting for interface %s, %d attempt", expectedIface, i)
		ifaceList, err := net.Interfaces()
		log.Trace(trace.Inside, "Agent: Entering podUpHandlerAsync()")
		if err != nil {
			log.Warn("Warning: Helper: failed to read net.Interfaces()")
		}
		for iface := range ifaceList {
			if ifaceList[iface].Name == expectedIface {
				return true
			}
		}
		time.Sleep(10 * time.Second)
	}
	return false
}
Пример #21
0
func stateInChainCounter(l *Lexer) stateFn {
	log.Trace(trace.Private, "In chain counter state")

	item := Item{Type: itemChainCounter}
	for {
		b := l.nextByte()
		c := string(b)

		switch c {
		case string(endOfText):
			return l.errorf("Error: unexpected EOF in chain counter section")
		case "\n":
			l.items <- item
			return rootState
		default:
			item.Body += c
		}
	}
}
Пример #22
0
func stateInRule(l *Lexer) stateFn {
	log.Trace(trace.Private, "In rule state")

	item := Item{Type: itemRule}
	for {
		b := l.nextByte()
		c := string(b)

		switch c {
		case string(endOfText):
			return l.errorf("Error: unexpected EOF in rule section")
		case " ":
			l.items <- item
			return stateRuleMatch
		default:
			item.Body += c
		}
	}
}
Пример #23
0
// stateInChain consumes chain name and checks for default policy token.
func stateInChain(l *Lexer) stateFn {
	log.Trace(trace.Private, "In chain state")

	item := Item{Type: itemChain}
	for {
		b := l.nextByte()
		c := string(b)

		switch c {
		case string(endOfText):
			return l.errorf("Error: unexpected EOF in chain section")
		case " ":
			l.items <- item
			return stateInChainPolicy
		case "\n":
			return l.errorf("Unexpectend end of line in chain state")
		default:
			item.Body += c
		}
	}
}
Пример #24
0
// statusHandler reports operational statistics.
func (a *Agent) statusHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	log.Trace(trace.Private, "Agent: Entering statusHandler()")
	fw, err := firewall.NewFirewall(a.getFirewallType())
	if err != nil {
		return nil, err
	}

	err = fw.Init(a.Helper.Executor, a.store, a.networkConfig)
	if err != nil {
		return nil, err
	}

	rules, err := fw.ListRules()
	if err != nil {
		return nil, err
	}
	ifaces, err := a.store.listNetIfs()
	if err != nil {
		return nil, err
	}
	status := Status{Rules: rules, Interfaces: ifaces}
	return status, nil
}
Пример #25
0
// Initialize implements the Initialize method of common.Service
// interface.
func (a *Agent) Initialize(client *common.RestClient) error {
	log.Trace(trace.Public, "Entering Agent.Initialize()")
	err := a.store.Connect()
	if err != nil {
		log.Error("Agent.Initialize() : Failed to connect to database.")
		return err
	}

	log.Info("Agent: Attempting to identify current host.")
	if err := a.identifyCurrentHost(); err != nil {
		log.Error("Agent: ", agentError(err))
		return agentError(err)
	}

	a.client = client
	// Ensure we have all the routes to our neighbours
	log.Info("Agent: ensuring interhost routes exist")
	if err := a.Helper.ensureInterHostRoutes(); err != nil {
		log.Error("Agent: ", agentError(err))
		return agentError(err)
	}
	return nil
}
Пример #26
0
func stateInRuleAction(l *Lexer) stateFn {
	log.Trace(trace.Private, "In rule action state")

	item := Item{Type: itemAction}
	for {
		b := l.nextByte()

		c := string(b)

		switch c {
		case string(endOfText):
			// Rule action is one of the places where
			// we can accept EOF. This is only legal when
			// single rule is being parsed.
			l.items <- item
			return l.errorEof("EOF reached in rule action section")
		case "\n":
			l.items <- item
			return rootState
		default:
			item.Body += c
		}
	}
}
Пример #27
0
// vmUpHandlerAsync does a number of operations on given endpoint to ensure
// it's connected:
// 1. Ensures interface is ready
// 2. Checks if DHCP is running
// 3. Creates ip route pointing new interface
// 4. Provisions static DHCP lease for new interface
// 5. Provisions firewall rules
func (a *Agent) vmUpHandlerAsync(netif NetIf) error {
	log.Trace(trace.Private, "Agent: Entering interfaceHandle()")
	currentProvider := a.getFirewallType()

	if !a.Helper.waitForIface(netif.Name) {
		// TODO should we resubmit failed interface in queue for later
		// retry ? ... considering oenstack will give up as well after
		// timeout
		return agentErrorString(fmt.Sprintf("Requested interface not available in time - %s", netif.Name))
	}

	// dhcpPid is only needed here for fail fast check
	// will try to poll the pid again in provisionLease
	log.Trace(trace.Inside, "Agent: Checking if DHCP is running")
	_, err := a.Helper.DhcpPid()
	if err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}
	err = a.store.addNetIf(&netif)
	if err != nil {
		return agentError(err)
	}
	log.Infof("Agent: Creating endpoint routes - %s", netif.Name)
	if err := a.Helper.ensureRouteToEndpoint(&netif); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}
	log.Infof("Agent: Provisioning DHCP - %s", netif.Name)
	if err := a.leaseFile.provisionLease(&netif, leaseAdd); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	log.Infof("Agent: Provisioning firewall - %s", netif.Name)
	fw, err := firewall.NewFirewall(currentProvider)
	if err != nil {
		return err
	}

	err = fw.Init(a.Helper.Executor, a.store, a.networkConfig)
	if err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	if err1 := fw.SetEndpoint(netif); err1 != nil {
		log.Error(agentError(err1))
		return agentError(err1)
	}

	var rules RuleSet
	switch currentProvider {
	case firewall.ShellexProvider:
		rules = OpenStackShellRules
	case firewall.IPTsaveProvider:
		rules = OpenStackSaveRestoreRules
	default:
		err := fmt.Errorf("Unkown firewall provider in vmUpHandler")
		log.Error(agentError(err))
		return agentError(err)
	}

	if err := prepareFirewallRules(fw, a.networkConfig, rules, currentProvider); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	if err := fw.ProvisionEndpoint(); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	log.Trace(trace.Inside, "All good", netif)
	return nil
}
Пример #28
0
// podUpHandlerAsync does a number of operations on given endpoint to ensure
// it's connected:
// 1. Ensures interface is ready
// 2. Creates ip route pointing new interface
// 3. Provisions firewall rules
func (a *Agent) podUpHandlerAsync(netReq NetworkRequest) error {
	log.Trace(trace.Private, "Agent: Entering podUpHandlerAsync()")
	currentProvider := a.getFirewallType()

	netif := netReq.NetIf
	if netif.Name == "" {
		return agentErrorString("Agent: Interface name required")
	}
	if !a.Helper.waitForIface(netif.Name) {
		// TODO should we resubmit failed interface in queue for later
		// retry ? ... considering openstack will give up as well after
		// timeout
		msg := fmt.Sprintf("Requested interface not available in time - %s", netif.Name)
		log.Warn("Agent: ", msg)
		return agentErrorString(msg)
	}
	log.Infof("Agent: Creating endpoint routes - %s", netif.Name)
	if err := a.Helper.ensureRouteToEndpoint(&netif); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	log.Infof("Agent: Provisioning firewall - %s", netif.Name)
	fw, err := firewall.NewFirewall(currentProvider)
	if err != nil {
		return err
	}

	err = fw.Init(a.Helper.Executor, a.store, a.networkConfig)
	if err != nil {
		return err
	}

	if err1 := fw.SetEndpoint(netif); err1 != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	var rules RuleSet
	switch currentProvider {
	case firewall.ShellexProvider:
		rules = KubeShellXRules
	case firewall.IPTsaveProvider:
		rules = KubeSaveRestoreRules
	default:
		err := fmt.Errorf("Unkown firewall provider in podUpHandler")
		log.Error(agentError(err))
		return agentError(err)
	}

	if err := prepareFirewallRules(fw, a.networkConfig, rules, currentProvider); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	if err := fw.ProvisionEndpoint(); err != nil {
		log.Error(agentError(err))
		return agentError(err)
	}

	log.Trace(trace.Inside, "Agent: All good", netif)
	return nil
}
Пример #29
0
func stateRuleMatch(l *Lexer) stateFn {
	log.Trace(trace.Private, "In rule match state")
	var exMarkConsumed, matchLiteralConsumed bool

	item := Item{Type: itemRuleMatch}
	for {
		b := l.nextByte()
		c := string(b)

		log.Trace(trace.Inside, "In rule match with char ", c)

		switch c {
		case string(endOfText):
			return l.errorf("Error: unexpected EOF in rule section")
		case "!":
			// exclamation mark can appear only once per match
			// and only before match literal
			if exMarkConsumed == true {
				return l.errorf("Unexpected ! in rules spec")
			}

			if matchLiteralConsumed {
				l.items <- item

				// put current '!' back into stream for the next iteration
				// can not fail
				_ = l.input.UnreadByte()

				return stateRuleMatch
			}

			exMarkConsumed = true
			item.Body += c
		case "-":
			// '-' dash can appear in 4 cases
			// in module literal like '-p' or '-m'
			// in module opts like '--dport'
			// in inside opts literal like '--to-destination' or inside body '-j MY-CHAIN'
			// in action '-j'
			onLiteral := false

			if l.expect("p ") || l.expect("m ") || l.expect("i ") || l.expect("o ") || l.expect("s ") || l.expect("d ") {
				// Single dash, single char and a space indicate module literal.
				onLiteral = true

			} else if l.expect("-") {
				// double dash indicate module opts
				// nothing to do, just let it be consumed
			} else if l.accept("j ") {
				l.items <- item
				return stateInRuleAction
			} // any other dash is inside a body

			if onLiteral {
				if matchLiteralConsumed {
					l.items <- item

					// put current '-' back into stream for the next iteration
					// can not fail
					_ = l.input.UnreadByte()

					return stateRuleMatch
				} else {
					matchLiteralConsumed = true
				}
			}

			item.Body += c

		default:
			item.Body += c
		}
	}
}
Пример #30
0
// identifyCurrentHost discovers network configuration
// of the host we are running on.
// We need to know public IP and Romana gateway IP of the current host.
// This is done by matching current host IP addresses against what topology
// service thinks the host address is.
// If no match is found we assume we are running on host which is not
// part of the Romana setup and spit error out.
func (a Agent) identifyCurrentHost() error {
	client, err := common.NewRestClient(common.GetRestClientConfig(a.config))

	if err != nil {
		return agentError(err)
	}
	topologyURL, err := client.GetServiceUrl("topology")
	if err != nil {
		return agentError(err)
	}
	index := common.IndexResponse{}
	err = client.Get(topologyURL, &index)
	if err != nil {
		return agentError(err)
	}
	dcURL := index.Links.FindByRel("datacenter")
	a.networkConfig.dc = common.Datacenter{}
	err = client.Get(dcURL, &a.networkConfig.dc)
	if err != nil {
		return agentError(err)
	}

	hostURL := index.Links.FindByRel("host-list")
	hosts := []common.Host{}
	err = client.Get(hostURL, &hosts)
	if err != nil {
		return agentError(err)
	}
	log.Trace(trace.Inside, "Retrieved hosts list, found", len(hosts), "hosts")

	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return err
	}

	log.Tracef(trace.Inside, "Searching %d interfaces for a matching host configuration: %v", len(addrs), addrs)

	// Find an interface that matches a Romana CIDR
	// and store that interface's IP address.
	// It will be used when configuring iptables and routes to tap interfaces.
	for i, host := range hosts {
		_, romanaCIDR, err := net.ParseCIDR(host.RomanaIp)
		if err != nil {
			log.Tracef(trace.Inside, "Unable to parse '%s' (%s). Skipping.", host.RomanaIp, err)
			continue
		}
		for _, addr := range addrs {
			ipnet, ok := addr.(*net.IPNet)
			if !ok {
				continue
			}
			if romanaCIDR.Contains(ipnet.IP) {
				// Check that it's the same subnet size
				s1, _ := romanaCIDR.Mask.Size()
				s2, _ := ipnet.Mask.Size()
				if s1 != s2 {
					continue
				}
				// OK, we're happy with this result
				a.networkConfig.romanaGW = ipnet.IP
				a.networkConfig.romanaGWMask = ipnet.Mask
				// Retain the other hosts that were listed.
				// This will be used for creating inter-host routes.
				a.networkConfig.otherHosts = append(a.networkConfig.otherHosts, hosts[0:i]...)
				a.networkConfig.otherHosts = append(a.networkConfig.otherHosts, hosts[i+1:]...)
				log.Trace(trace.Inside, "Found match for CIDR", romanaCIDR, "using address", ipnet.IP)
				return nil
			}
		}
	}
	return agentErrorString("Unable to find interface matching any Romana CIDR")
}