func (tsvc *TenantSvc) Initialize() error { err := tsvc.store.connect() if err != nil { return err } client, err := common.NewRestClient("", tsvc.config.Common.Api.RestTimeoutMillis) if err != nil { return err } topologyURL, err := client.GetServiceUrl(tsvc.config.Common.Api.RootServiceUrl, "topology") if err != nil { return err } index := common.IndexResponse{} err = client.Get(topologyURL, &index) if err != nil { return err } dcURL := index.Links.FindByRel("datacenter") dc := common.Datacenter{} err = client.Get(dcURL, &dc) if err != nil { return err } // TODO should this always be queried? tsvc.dc = dc return nil }
func (ipam *IPAMSvc) Initialize() error { log.Println("Entering ipam.Initialize()") err := ipam.store.connect() if err != nil { return err } client, err := common.NewRestClient("", common.DefaultRestTimeout) if err != nil { return err } topologyURL, err := client.GetServiceUrl(ipam.config.Common.Api.RootServiceUrl, "topology") if err != nil { return err } index := common.IndexResponse{} err = client.Get(topologyURL, &index) if err != nil { return err } dcURL := index.Links.FindByRel("datacenter") dc := common.Datacenter{} log.Printf("IPAM received datacenter information from topology service: %s\n", dc) err = client.Get(dcURL, &dc) if err != nil { return err } // TODO should this always be queried? ipam.dc = dc return nil }
// Test the topology service func (s *MySuite) TestTopology(c *check.C) { myLog(c, "Entering TestTopology()") dir, _ := os.Getwd() myLog(c, "In", dir) myLog(c, "Starting topology service") channelTop, addr, err := Run(s.rootUrl) if err != nil { c.Error(err) } msg := <-channelTop myLog(c, "Topology service said:", msg) addr = "http://" + addr client, err := common.NewRestClient(addr, common.DefaultRestTimeout) if err != nil { c.Error(err) } myLog(c, "Calling ", addr) topIndex := &common.IndexResponse{} err = client.Get("/", &topIndex) if err != nil { c.Error(err) } c.Assert(topIndex.ServiceName, check.Equals, "topology") hostsRelUrl := topIndex.Links.FindByRel("host-list") hostsUrl := addr + hostsRelUrl myLog(c, "Host list URL: ", hostsUrl) // Get list of hosts - should be empty for now. var hostList []Host client.Get(hostsRelUrl, &hostList) myLog(c, "Host list: ", hostList) c.Assert(len(hostList), check.Equals, 0) newHostReq := common.HostMessage{Ip: "10.10.10.10", AgentPort: 9999, Name: "host10"} newHostResp := common.HostMessage{} client.Post(hostsRelUrl, newHostReq, &newHostResp) myLog(c, "Response: ", newHostResp) c.Assert(newHostResp.Ip, check.Equals, "10.10.10.10") c.Assert(newHostResp.Id, check.Equals, "1") newHostReq = common.HostMessage{Ip: "10.10.10.11", AgentPort: 9999, Name: "host11"} newHostResp = common.HostMessage{} client.Post(hostsRelUrl, newHostReq, &newHostResp) myLog(c, "Response: ", newHostResp) c.Assert(newHostResp.Ip, check.Equals, "10.10.10.11") c.Assert(newHostResp.Id, check.Equals, "2") var hostList2 []Host client.Get(hostsRelUrl, &hostList2) myLog(c, "Host list: ", hostList2) c.Assert(len(hostList2), check.Equals, 2) }
// Runs Tenant service func Run(rootServiceUrl string) (chan common.ServiceMessage, string, error) { tsvc := &TenantSvc{} client, err := common.NewRestClient(rootServiceUrl, common.DefaultRestTimeout) if err != nil { return nil, "", err } config, err := client.GetServiceConfig(rootServiceUrl, tsvc) if err != nil { return nil, "", err } return common.InitializeService(tsvc, *config) }
// Runs IPAM service func Run(rootServiceUrl string) (chan common.ServiceMessage, string, error) { client, err := common.NewRestClient(rootServiceUrl, common.DefaultRestTimeout) if err != nil { return nil, "", err } ipam := &IPAMSvc{} config, err := client.GetServiceConfig(rootServiceUrl, ipam) if err != nil { return nil, "", err } return common.InitializeService(ipam, *config) }
// Run configures and runs listener service. func Run(rootServiceURL string, cred *common.Credential) (*common.RestServiceInfo, error) { clientConfig := common.GetDefaultRestClientConfig(rootServiceURL) clientConfig.Credential = cred client, err := common.NewRestClient(clientConfig) if err != nil { return nil, err } KubeListener := &KubeListener{} KubeListener.restClient = client config, err := client.GetServiceConfig(KubeListener.Name()) if err != nil { return nil, err } return common.InitializeService(KubeListener, *config, cred) }
// Run runs the agent service. func Run(rootServiceURL string) (chan common.ServiceMessage, string, error) { client, err := common.NewRestClient("", common.DefaultRestTimeout) if err != nil { return nil, "", err } agent := &Agent{} helper := NewAgentHelper(agent) agent.Helper = &helper log.Printf("Agent: Getting configuration from %s", rootServiceURL) config, err := client.GetServiceConfig(rootServiceURL, agent) if err != nil { return nil, "", err } return common.InitializeService(agent, *config) }
// Test the service list. func TestServiceList(t *testing.T) { fmt.Println("Entering TestServiceList") dir, _ := os.Getwd() fmt.Println("In", dir) yamlFileName := "../common/testdata/romana.sample.yaml" common.MockPortsInConfig(yamlFileName) fmt.Println("Calling Run()") channel, addr, err := Run("/tmp/romana.yaml") if err != nil { fmt.Println(err.Error()) t.FailNow() } fmt.Println("Waiting for message") msg := <-channel fmt.Println("Root service said:", msg) _, err = common.ReadConfig("/tmp/romana.yaml") if err != nil { t.Error(err) t.FailNow() } addr = fmt.Sprintf("http://%s", addr) client, err := common.NewRestClient(addr, common.DefaultRestTimeout) if err != nil { t.Error(err) t.FailNow() } r := common.IndexResponse{} err = client.Get("", &r) if err != nil { t.Error(err) t.FailNow() } fmt.Println("Received: ", r) svcName := r.ServiceName fmt.Println("Service name:", svcName) if svcName != "root" { t.Errorf("Expected serviceName to be root, got %s", svcName) } }
// Runs topology service func CreateSchema(rootServiceUrl string, overwrite bool) error { log.Println("In CreateSchema(", rootServiceUrl, ",", overwrite, ")") client, err := common.NewRestClient("", common.DefaultRestTimeout) if err != nil { return err } topologyService := &TopologySvc{} config, err := client.GetServiceConfig(rootServiceUrl, topologyService) if err != nil { return err } err = topologyService.SetConfig(*config) if err != nil { return err } return topologyService.store.createSchema(overwrite) }
// Runs topology service func CreateSchema(rootServiceUrl string, overwrite bool) error { log.Println("In CreateSchema(", rootServiceUrl, ",", overwrite, ")") ipamSvc := &IPAMSvc{} client, err := common.NewRestClient("", common.DefaultRestTimeout) if err != nil { return err } config, err := client.GetServiceConfig(rootServiceUrl, ipamSvc) if err != nil { return err } err = ipamSvc.SetConfig(*config) if err != nil { return err } return ipamSvc.store.createSchema(overwrite) }
// romanaHostAdd connects to romana API and adds a node to // the romana cluster. func romanaHostAdd(node *v1.Node) error { if node.Name == "" || len(node.Status.Addresses) < 1 { log.Printf("Error: received invalid host name or IP Address: (%s)", node) return errors.New("Error: received invalid host name or IP Address.") } hostname := node.Name hostIP := node.Status.Addresses[0].Address rootURL := config.GetString("RootURL") client, err := common.NewRestClient(common.GetDefaultRestClientConfig(rootURL)) if err != nil { return err } topologyURL, err := client.GetServiceUrl("topology") if err != nil { return err } index := common.IndexResponse{} err = client.Get(topologyURL, &index) if err != nil { return err } host := common.Host{ Name: hostname, Ip: hostIP, } data := common.Host{} err = client.Post(topologyURL+"/hosts", host, &data) if err != nil { log.Printf("Error adding host (%s).\n", hostname) return err } log.Printf("Host (%s) added successfully.\n", hostname) return nil }
// Test the service list. func (s *MySuite) TestAuth(c *check.C) { fmt.Println("Entering TestServiceList") dir, _ := os.Getwd() fmt.Println("In", dir) err := s.RomanaTestSuite.MockConfig("../common/testdata/romana.auth.yaml") if err != nil { c.Fatal(err) } fmt.Printf("Calling Run(%s)", s.RomanaTestSuite.ConfigFile) svcInfo, err := Run(s.RomanaTestSuite.ConfigFile) if err != nil { c.Fatal(err) } fmt.Println("Waiting for message") msg := <-svcInfo.Channel fmt.Println("Root service said:", msg) addr := fmt.Sprintf("http://%s", svcInfo.Address) clientConfig := common.GetDefaultRestClientConfig(addr) clientConfig.Credential = &common.Credential{Type: common.CredentialUsernamePassword, Username: "******", Password: "******"} client, err := common.NewRestClient(clientConfig) if err != nil { c.Fatal(err) } r := common.IndexResponse{} err = client.Get("", &r) if err != nil { c.Fatal(err) } fmt.Println("Received: ", r) svcName := r.ServiceName fmt.Printf("Service name: %s", svcName) if svcName != "root" { c.Fatalf("Expected serviceName to be root, got %s", svcName) } }
// Test the service list. func (s *MySuite) TestServiceList(c *check.C) { fmt.Println("Entering TestServiceList") dir, _ := os.Getwd() fmt.Println("In", dir) err := s.RomanaTestSuite.MockConfig(common.DefaultTestConfigFile) if err != nil { c.Fatal(err) } fmt.Printf("Calling Run(%s)", s.RomanaTestSuite.ConfigFile) svcInfo, err := Run(s.RomanaTestSuite.ConfigFile) if err != nil { c.Fatal(err) } fmt.Println("Waiting for message") msg := <-svcInfo.Channel fmt.Println("Root service said:", msg) rootURL := fmt.Sprintf("http://%s", svcInfo.Address) client, err := common.NewRestClient(common.GetDefaultRestClientConfig(rootURL)) if err != nil { c.Fatal(err) } r := common.IndexResponse{} err = client.Get("", &r) if err != nil { c.Fatal(err) } fmt.Println("Received: ", r) svcName := r.ServiceName fmt.Printf("Service name: %s", svcName) if svcName != "root" { c.Fatalf("Expected serviceName to be root, got %s", svcName) } }
// 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("", a.config.Common.Api.RestTimeoutMillis) if err != nil { return agentError(err) } topologyURL, err := client.GetServiceUrl(a.config.Common.Api.RootServiceUrl, "topology") if err != nil { return agentError(err) } index := common.IndexResponse{} err = client.Get(topologyURL, &index) if err != nil { return agentError(err) } log.Println("4") 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.HostMessage{} log.Println("5") err = client.Get(hostURL, &hosts) if err != nil { return agentError(err) } log.Println("6") // Walking through all interfaces on a host and looking for a // matching interface address in configuration. addrs, _ := net.InterfaceAddrs() for i := range addrs { romanaIP, _, err := net.ParseCIDR(addrs[i].String()) if err != nil { log.Printf("Failed to parse %s", addrs[i].String()) return err } // Walking through host addresses in our config and looking // for a match to current interface address for j := range hosts { _, romanaNet, err := net.ParseCIDR(hosts[j].RomanaIp) if err != nil { log.Printf("Failed to parse %s", hosts[j].RomanaIp) return err } log.Printf("Init:IdentifyCurrentHost %s belongs to %s %s", romanaNet, romanaIP, romanaNet.Contains(romanaIP)) // Found it if romanaNet.Contains(romanaIP) { a.networkConfig.currentHostIP = net.ParseIP(hosts[j].Ip) a.networkConfig.currentHostGW = romanaIP a.networkConfig.currentHostGWNet = *romanaNet a.networkConfig.currentHostGWNetSize, _ = romanaNet.Mask.Size() a.networkConfig.currentHostIndex = j a.networkConfig.hosts = hosts return nil } } } return nil // return wrongHostError() }
// getRestClient gets the rest client instance with the // configured root URL and the credential object that was // built at initalization. func getRestClient() (*common.RestClient, error) { rootURL := config.GetString("RootURL") cfg := common.GetDefaultRestClientConfig(rootURL) cfg.Credential = credential return common.NewRestClient(cfg) }
func (s *MySuite) TestPolicy(c *check.C) { cfg := &common.ServiceConfig{Common: common.CommonConfig{Api: &common.Api{Port: 0, RestTimeoutMillis: 100}}} log.Printf("Test: Mock service config:\n\t%#v\n\t%#v\n", cfg.Common.Api, cfg.ServiceSpecific) svc := &mockSvc{mySuite: s} svc.tenants = make(map[uint64]string) svc.tenantsStr = make(map[string]uint64) svc.segments = make(map[uint64]string) svc.segmentsStr = make(map[string]uint64) svcInfo, err := common.InitializeService(svc, *cfg, nil) if err != nil { c.Error(err) c.FailNow() } msg := <-svcInfo.Channel log.Printf("Test: Mock service says %s; listening on %s\n", msg, svcInfo.Address) addrComponents := strings.Split(svcInfo.Address, ":") portStr := addrComponents[len(addrComponents)-1] s.servicePort, err = strconv.ParseUint(portStr, 10, 64) if err != nil { c.Error(err) c.FailNow() } s.serviceURL = fmt.Sprintf("http://%s", svcInfo.Address) log.Printf("Test: Mock service listens at %s\n", s.serviceURL) polSvc := &PolicySvc{} err = common.SimpleOverwriteSchema(polSvc, s.serviceURL) if err != nil { c.Fatal(err) } log.Printf("Policy schema created.") svcInfo, err = common.SimpleStartService(polSvc, s.serviceURL) if err != nil { c.Fatal(err) } msg = <-svcInfo.Channel fmt.Printf("Policy service listening %s on said: %s", svcInfo.Address, msg) clientConfig := common.GetDefaultRestClientConfig(s.serviceURL) client, err := common.NewRestClient(clientConfig) if err != nil { c.Fatal(err) } polURL := "http://" + svcInfo.Address + "/policies" log.Println("1. Add policy pol1") policyIn := common.Policy{} err = json.Unmarshal([]byte(romanaPolicy1), &policyIn) if err != nil { c.Fatal(err) c.FailNow() } policyOut := common.Policy{} err = client.Post(polURL, policyIn, &policyOut) if err != nil { c.Error(err) c.FailNow() } log.Printf("Added policy result: %s", policyOut) c.Assert(policyOut.Name, check.Equals, "pol1") c.Assert(policyOut.ID, check.Equals, uint64(1)) c.Assert(len(policyOut.AppliedTo), check.Equals, len(policyIn.AppliedTo)) c.Assert(len(policyOut.Ingress[0].Peers), check.Equals, len(policyIn.Ingress[0].Peers)) c.Assert(client.GetStatusCode(), check.Equals, 200) pol1ExternalID := policyIn.ExternalID policyIn.ExternalID = "asdfghjkl" policyIn.ID = policyOut.ID log.Printf("2. Add policy again with different External ID %s but same ID %d", policyIn.ExternalID, policyIn.ID) err = client.Post(polURL, policyIn, &policyOut) c.Assert(err.(common.HttpError).StatusCode, check.Equals, http.StatusConflict) log.Printf("2. Result: %+v", policyOut) log.Println("3. Add policy again") policyIn.ExternalID = pol1ExternalID policyIn.ID = 0 err = client.Post(polURL, policyIn, &policyOut) c.Assert(err.(common.HttpError).StatusCode, check.Equals, http.StatusConflict) log.Printf("3. Result: %+v", policyOut) log.Println("4. Add policy pol2") err = json.Unmarshal([]byte(romanaPolicy2), &policyIn) if err != nil { c.Fatal(err) } err = client.Post(polURL, policyIn, &policyOut) if err != nil { c.Fatal(err) } log.Printf("Added policy result: %s", policyOut) c.Assert(client.GetStatusCode(), check.Equals, 200) c.Assert(policyOut.Name, check.Equals, "pol2") log.Println("5. Add default policy") one := uint64(1) defPol := common.Policy{ Direction: common.PolicyDirectionIngress, Name: "default", ExternalID: "default", AppliedTo: []common.Endpoint{{TenantNetworkID: &one}}, Ingress: []common.RomanaIngress{ common.RomanaIngress{ Peers: []common.Endpoint{{Peer: common.Wildcard}}, Rules: []common.Rule{{Protocol: common.Wildcard}}, }, }, } err = client.Post(polURL, defPol, &policyOut) if err != nil { c.Fatal(err) } log.Printf("Added policy result: %s", policyOut) c.Assert(client.GetStatusCode(), check.Equals, 200) c.Assert(policyOut.Name, check.Equals, "default") log.Println("6. Test list policies - should have 3.") var policies []common.Policy err = client.Get(polURL, &policies) if err != nil { c.Fatal(err) } c.Assert(len(policies), check.Equals, 3) c.Assert(client.GetStatusCode(), check.Equals, 200) c.Assert(policies[0].Name, check.Equals, "pol1") c.Assert(policies[1].Name, check.Equals, "pol2") c.Assert(policies[2].Name, check.Equals, "default") log.Println("7. Test get policy.") policyGet := common.Policy{} err = client.Get(polURL+"/1", &policyGet) if err != nil { c.Fatal(err) } c.Assert(policyGet.Name, check.Equals, policies[0].Name) c.Assert(client.GetStatusCode(), check.Equals, 200) log.Println("8. Test delete by ID - delete pol1") policyOut = common.Policy{} err = client.Delete(polURL+"/1", nil, &policyOut) if err != nil { c.Fatal(err) } log.Printf("Deleted policy result: %s", policyOut) c.Assert(policyOut.Name, check.Equals, "pol1") c.Assert(policyOut.ID, check.Equals, uint64(1)) c.Assert(client.GetStatusCode(), check.Equals, 200) log.Println("9. Test list policies - should have 2 now - pol2 and default.") err = client.Get(polURL, &policies) if err != nil { c.Fatal(err) } c.Assert(len(policies), check.Equals, 2) c.Assert(policies[0].Name, check.Equals, "pol2") c.Assert(policies[1].Name, check.Equals, "default") c.Assert(client.GetStatusCode(), check.Equals, 200) log.Println("10. Test delete by ExternalID - delete policy 2") err = json.Unmarshal([]byte(romanaPolicy2), &policyIn) if err != nil { c.Fatal(err) } log.Printf("Unmarshaled %s to %v", romanaPolicy2, policyIn) policyOut = common.Policy{} err = client.Delete(polURL, policyIn, &policyOut) if err != nil { c.Fatal(err) } log.Printf("Deleted policy result: %s", policyOut) c.Assert(client.GetStatusCode(), check.Equals, 200) c.Assert(policyOut.Name, check.Equals, policyIn.Name) log.Println("10. Test list policies - should have 1 now - only default") err = client.Get(polURL, &policies) if err != nil { c.Fatal(err) } c.Assert(client.GetStatusCode(), check.Equals, 200) c.Assert(len(policies), check.Equals, 1) c.Assert(policies[0].Name, check.Equals, "default") log.Println("11. Test find by name policies - should find it") findURL := "http://" + svcInfo.Address + "/find/policies" err = client.Get(findURL+"/default", &policyOut) if err != nil { c.Fatal(err) } c.Assert(policyOut.Name, check.Equals, "default") log.Println("12. Test find by name policies with non-existent policy - should NOT find it") err = client.Get(findURL+"/blabla", &policyOut) httpErr := err.(common.HttpError) c.Assert(client.GetStatusCode(), check.Equals, http.StatusNotFound) c.Assert(httpErr.ResourceType, check.Equals, "policy") c.Assert(httpErr.StatusCode, check.Equals, http.StatusNotFound) c.Assert(httpErr.ResourceID, check.Equals, "blabla") log.Printf("%v", err) log.Println("13. Test delete by ExternalID - delete default policy") policyOut = common.Policy{} err = client.Delete(polURL, defPol, &policyOut) if err != nil { c.Fatal(err) } log.Printf("Deleted policy result: %s", policyOut) c.Assert(policyOut.Name, check.Equals, defPol.Name) c.Assert(client.GetStatusCode(), check.Equals, 200) log.Println("14. Test list policies - should have 0 now") err = client.Get(polURL, &policies) if err != nil { c.Fatal(err) } c.Assert(len(policies), check.Equals, 0) log.Println("15. Test delete by ExternalID - delete default policy - should be Not Found error now") policyOut = common.Policy{} err = client.Delete(polURL, defPol, &policyOut) if err == nil { panic("Expected error") } httpErr = err.(common.HttpError) c.Assert(client.GetStatusCode(), check.Equals, http.StatusNotFound) c.Assert(httpErr.ResourceType, check.Equals, "policy") c.Assert(httpErr.StatusCode, check.Equals, http.StatusNotFound) // TODO // Important! This should really be done in policy agent. // Only done here as temporary measure. id := makeId(defPol.AppliedTo, defPol.Name) c.Assert(httpErr.ResourceID, check.Equals, id) // c.Assert(httpErr.ResourceID, check.Equals, "default") log.Printf("%v", err) }
func (s *MySuite) TestHooks(c *check.C) { fmt.Println("Entering TestHooks") dir, _ := os.Getwd() fmt.Println("In", dir) yamlFileName := "../common/testdata/romana.hooks.yaml" svcInfo, err := Run(yamlFileName) if err != nil { fmt.Println(err.Error()) } fmt.Println("Waiting for message") msg := <-svcInfo.Channel fmt.Println("Root service said:", msg) rootURL := fmt.Sprintf("http://%s", svcInfo.Address) client, err := common.NewRestClient(common.GetDefaultRestClientConfig(rootURL)) if err != nil { c.Fatal(err) } result1 := make(map[string]interface{}) err = client.Get("/config/ipam", &result1) if err != nil { c.Fatal(err) } fmt.Println("Received: ", result1) file, err := os.Open("/tmp/hook.txt") if err != nil { c.Fatal(err) } data := make([]byte, 1024) n, err := file.Read(data) if err != nil { c.Fatal(err) } str := strings.TrimSpace(string(data[0:n])) fmt.Printf("Hook output: [%s]", str) expect := "Hello, world and body= serviceName=ipam" if str != expect { c.Fatalf("Expected %s, received %s", expect, str) } url := fmt.Sprintf("%s/config/ipam/port", rootURL) result2 := make(map[string]interface{}) portMsg := common.PortUpdateMessage{Port: 12345} err = client.Post(url, portMsg, &result2) fmt.Printf("Got %v", err) if err == nil { c.Fatal("Expected error, got nothing") } fmt.Println("Received: ", result2) file, err = os.Open("/tmp/hook_bad.txt") if err != nil { c.Fatal(err) } data = make([]byte, 1024) n, err = file.Read(data) if err != nil { c.Fatal(err) } str = strings.TrimSpace(string(data[0:n])) fmt.Printf("Hook output: [%s]", str) expect = "Good-bye, cruel world" if str != expect { c.Fatalf("Expected %s, received %s", expect, str) } }
// handleHost handles request for a specific host's info func (ipam *IPAMSvc) legacyAllocateIpByName(input interface{}, ctx common.RestContext) (interface{}, error) { log.Printf("LEgacy 1\n") tenantName := ctx.QueryVariables["tenantName"][0] segmentName := ctx.QueryVariables["segmentName"][0] hostName := ctx.QueryVariables["hostName"][0] names := ctx.QueryVariables["instanceName"] name := "VM" if len(names) > 0 { name = names[0] } vm := Vm{} vm.Name = name client, err := common.NewRestClient("", ipam.config.Common.Api.RestTimeoutMillis) if err != nil { return nil, err } // Get host info from topology service topoUrl, err := client.GetServiceUrl(ipam.config.Common.Api.RootServiceUrl, "topology") if err != nil { return nil, err } index := common.IndexResponse{} err = client.Get(topoUrl, &index) if err != nil { return nil, err } hostsUrl := index.Links.FindByRel("host-list") var hosts []common.HostMessage err = client.Get(hostsUrl, &hosts) if err != nil { return nil, err } found := false for i := range hosts { if hosts[i].Name == hostName { found = true vm.HostId = hosts[i].Id break } } if !found { msg := fmt.Sprintf("Host with name %s not found", hostName) log.Printf(msg) return nil, errors.New(msg) } log.Printf("Host name %s has ID %s", hostName, vm.HostId) tenantSvcUrl, err := client.GetServiceUrl(ipam.config.Common.Api.RootServiceUrl, "tenant") if err != nil { return nil, err } // TODO follow links once tenant service supports it. For now... tenantsUrl := fmt.Sprintf("%s/tenants", tenantSvcUrl) var tenants []tenant.Tenant err = client.Get(tenantsUrl, &tenants) if err != nil { return nil, err } found = false var i int for i = range tenants { if tenants[i].Name == tenantName { found = true vm.TenantId = fmt.Sprintf("%d", tenants[i].Id) log.Printf("IPAM: Tenant name %s has ID %s, original %d\n", tenantName, vm.TenantId, tenants[i].Id) break } } if !found { return nil, errors.New("Tenant with name " + tenantName + " not found") } log.Printf("IPAM: Tenant name %s has ID %s, original %d\n", tenantName, vm.TenantId, tenants[i].Id) segmentsUrl := fmt.Sprintf("/tenants/%s/segments", vm.TenantId) var segments []tenant.Segment err = client.Get(segmentsUrl, &segments) if err != nil { return nil, err } found = false for _, s := range segments { if s.Name == segmentName { found = true vm.SegmentId = fmt.Sprintf("%d", s.Id) break } } if !found { return nil, errors.New("Segment with name " + hostName + " not found") } log.Printf("Sement name %s has ID %s", segmentName, vm.SegmentId) return ipam.addVm(&vm, ctx) }
// Test the topology service func (s *MySuite) TestTopology(c *check.C) { myLog(c, "Entering TestTopology()") dir, _ := os.Getwd() myLog(c, "In", dir) myLog(c, "Starting topology service") topoSvc := &TopologySvc{} svcInfo, err := common.SimpleStartService(topoSvc, s.rootURL) if err != nil { c.Error(err) } msg := <-svcInfo.Channel myLog(c, "Topology service said:", msg) addr := "http://" + svcInfo.Address client, err := common.NewRestClient(common.GetDefaultRestClientConfig(addr)) if err != nil { c.Error(err) } myLog(c, "Calling ", addr) topIndex := &common.IndexResponse{} err = client.Get("/", &topIndex) if err != nil { c.Error(err) c.FailNow() } c.Assert(topIndex.ServiceName, check.Equals, "topology") hostsRelURL := topIndex.Links.FindByRel("host-list") hostsURL := addr + hostsRelURL myLog(c, "Host list URL: ", hostsURL) // Get list of hosts - should be empty for now. var hostList []common.Host err = client.Get(hostsRelURL, &hostList) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Host list: ", hostList) c.Assert(len(hostList), check.Equals, 0) newHostReq := common.Host{Ip: "10.10.10.10", AgentPort: 9999, Name: "host10", RomanaIp: "15.15.15.15"} newHostResp := common.Host{} err = client.Post(hostsRelURL, newHostReq, &newHostResp) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Response: ", newHostResp) myLog(c, "Waiting for....", time.Hour) // time.Sleep(time.Hour) c.Assert(newHostResp.Ip, check.Equals, "10.10.10.10") c.Assert(newHostResp.ID, check.Equals, uint64(1)) newHostReq = common.Host{Ip: "10.10.10.11", AgentPort: 9999, Name: "host11", RomanaIp: "15.15.15.16"} newHostResp = common.Host{} err = client.Post(hostsRelURL, newHostReq, &newHostResp) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Response: ", newHostResp) c.Assert(newHostResp.ID, check.Equals, uint64(2)) err = client.Post(hostsRelURL, newHostReq, &newHostResp) httpErr := err.(common.HttpError) myLog(c, "Attempt to add duplicate host: %v", httpErr) c.Assert(httpErr.StatusCode, check.Equals, 409) newHostReqWithoutRomanaIP := common.Host{Ip: "10.10.10.12", AgentPort: 9999, Name: "host12"} newHostRespWithoutRomanaIP := common.Host{} err = client.Post(hostsRelURL, newHostReqWithoutRomanaIP, &newHostRespWithoutRomanaIP) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Response: ", newHostRespWithoutRomanaIP) c.Assert(newHostRespWithoutRomanaIP.Ip, check.Equals, "10.10.10.12") c.Assert(newHostRespWithoutRomanaIP.RomanaIp, check.Equals, "10.2.0.0/16") c.Assert(newHostRespWithoutRomanaIP.ID, check.Equals, uint64(3)) newHostReqWithoutRomanaIP = common.Host{Ip: "10.10.10.13", AgentPort: 9999, Name: "host13"} newHostRespWithoutRomanaIP = common.Host{} err = client.Post(hostsRelURL, newHostReqWithoutRomanaIP, &newHostRespWithoutRomanaIP) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Response: ", newHostRespWithoutRomanaIP) c.Assert(newHostRespWithoutRomanaIP.Ip, check.Equals, "10.10.10.13") c.Assert(newHostRespWithoutRomanaIP.RomanaIp, check.Equals, "10.3.0.0/16") c.Assert(newHostRespWithoutRomanaIP.ID, check.Equals, uint64(4)) // TODO: auto generation of romana cidr currently don't // handle manually assigned one gracefully, thus tests // to be added here once that support is added. var hostList2 []common.Host err = client.Get(hostsRelURL, &hostList2) if err != nil { c.Error(err) c.FailNow() } myLog(c, "Host list: ", hostList2) c.Assert(len(hostList2), check.Equals, 4) }
// Test the integration with root and topology service func (s *MySuite) TestIntegration(c *check.C) { myLog(c, "Entering TestIntegration()") dir, _ := os.Getwd() myLog(c, "In", dir) // 1. Start topology service myLog(c, "STARTING TOPOLOGY SERVICE") channelTop, topoAddr, err := topology.Run(s.rootUrl) if err != nil { c.Error(err) } msg := <-channelTop myLog(c, "Topology service said:", msg) // 2. Add some hosts to topology service and test. topoAddr = "http://" + topoAddr client, err := common.NewRestClient(topoAddr, common.DefaultRestTimeout) if err != nil { c.Error(err) } myLog(c, "Calling ", topoAddr) topIndex := &common.IndexResponse{} err = client.Get("/", &topIndex) if err != nil { c.Error(err) } c.Assert(topIndex.ServiceName, check.Equals, "topology") hostsRelUrl := topIndex.Links.FindByRel("host-list") hostsUrl := topoAddr + hostsRelUrl myLog(c, "Host list URL: ", hostsUrl) // Get list of hosts - should be empty for now. var hostList []common.HostMessage client.Get(hostsRelUrl, &hostList) myLog(c, "Host list: ", hostList) c.Assert(len(hostList), check.Equals, 0) newHostReq := common.HostMessage{Ip: "10.10.10.10", RomanaIp: "10.64.0.0/16", AgentPort: 9999, Name: "HOST1000"} host1 := common.HostMessage{} client.Post(hostsRelUrl, newHostReq, &host1) myLog(c, "Response: ", host1) c.Assert(host1.Ip, check.Equals, "10.10.10.10") c.Assert(host1.Id, check.Equals, "1") // newHostReq = common.HostMessage{Ip: "10.10.10.11", RomanaIp: "10.65.0.0/16", AgentPort: 9999, Name: "HOST2000"} host2 := common.HostMessage{} client.Post(hostsRelUrl, newHostReq, &host2) myLog(c, "Response: ", host2) c.Assert(host2.Ip, check.Equals, "10.10.10.11") c.Assert(host2.Id, check.Equals, "2") var hostList2 []common.HostMessage client.Get(hostsRelUrl, &hostList2) myLog(c, "Host list: ", hostList2) c.Assert(len(hostList2), check.Equals, 2) // 3. Start tenant service myLog(c, "STARTING TENANT SERVICE") channelTen, tenantAddr, err := tenant.Run(s.rootUrl) if err != nil { c.Error(err) } tenantAddr = "http://" + tenantAddr msg = <-channelTen myLog(c, "Tenant service said:", msg) client, err = common.NewRestClient(tenantAddr, common.DefaultRestTimeout) if err != nil { c.Error(err) } // 4. Add a tenant and a segment err = client.NewUrl(tenantAddr) if err != nil { c.Error(err) } // Add first tenant tIn := tenant.Tenant{Name: "t1"} tOut := tenant.Tenant{} err = client.Post("/tenants", tIn, &tOut) if err != nil { c.Error(err) } t1Id := tOut.Id myLog(c, "Tenant", tOut) // Add second tenant tIn = tenant.Tenant{Name: "t2"} tOut = tenant.Tenant{} err = client.Post("/tenants", tIn, &tOut) if err != nil { c.Error(err) } t2Id := tOut.Id myLog(c, "Tenant", tOut) // Find first tenant tOut2 := tenant.Tenant{} tenant1Path := fmt.Sprintf("/tenants/%d", t1Id) err = client.Get(tenant1Path, &tOut2) if err != nil { c.Error(err) } myLog(c, "Found", tOut2) // Add 2 segments to tenant 1 sIn := tenant.Segment{Name: "s1", TenantId: t1Id} sOut := tenant.Segment{} err = client.Post(tenant1Path+"/segments", sIn, &sOut) if err != nil { c.Error(err) } myLog(c, "Added segment s1 to t1: ", sOut) sIn = tenant.Segment{Name: "s2", TenantId: t1Id} sOut = tenant.Segment{} err = client.Post(tenant1Path+"/segments", sIn, &sOut) if err != nil { c.Error(err) } myLog(c, "Added segment s2 to t1: ", sOut) // Add 2 segments to tenant 2 tenant2Path := fmt.Sprintf("/tenants/%d", t2Id) sIn = tenant.Segment{Name: "s1", TenantId: t2Id} sOut = tenant.Segment{} err = client.Post(tenant2Path+"/segments", sIn, &sOut) if err != nil { c.Error(err) } myLog(c, "Added segment s1 to t2: ", sOut) sIn = tenant.Segment{Name: "s2", TenantId: t2Id} sOut = tenant.Segment{} err = client.Post(tenant2Path+"/segments", sIn, &sOut) if err != nil { c.Error(err) } myLog(c, "Added segment s2 to t2: ", sOut) // 4. Start IPAM service myLog(c, "STARTING IPAM SERVICE") channelIpam, ipamAddr, err := ipam.Run(s.rootUrl) if err != nil { c.Error(err) } ipamAddr = fmt.Sprintf("http://%s", ipamAddr) msg = <-channelIpam myLog(c, "IPAM service said: ", msg) client, err = common.NewRestClient(ipamAddr, common.DefaultRestTimeout) if err != nil { c.Error(err) } // Get first IP vmIn := ipam.Vm{Name: "vm1", TenantId: fmt.Sprintf("%d", tOut.Id), SegmentId: fmt.Sprintf("%d", sOut.Id), HostId: host2.Id} vmOut := ipam.Vm{} err = client.Post("/vms", vmIn, &vmOut) if err != nil { c.Error(err) } myLog(c, "Received:", vmOut) myLog(c, "IP:", vmOut.Ip) // Get second IP vmIn = ipam.Vm{Name: "vm2", TenantId: fmt.Sprintf("%d", tOut.Id), SegmentId: fmt.Sprintf("%d", sOut.Id), HostId: host2.Id} vmOut = ipam.Vm{} err = client.Post("/vms", vmIn, &vmOut) if err != nil { c.Error(err) } myLog(c, "Received:", vmOut) myLog(c, "IP:", vmOut.Ip) // Try legacy request vmOut = ipam.Vm{} legacyUrl := "/allocateIpByName?tenantName=t1&segmentName=s1&hostName=HOST2000&instanceName=bla" myLog(c, "Calling legacy URL", legacyUrl) err = client.Get(legacyUrl, &vmOut) if err != nil { myLog(c, "Error %s\n", err) c.Error(err) } myLog(c, "Legacy received:", vmOut) myLog(c, "Legacy IP:", vmOut.Ip) // 5. Start Agent service myLog(c, "STARTING Agent SERVICE") channelAgent, _, err := agent.Run(s.rootUrl) if err != nil { c.Error(err) } msg = <-channelAgent myLog(c, "Agent service said:", msg) }
// handleHost handles request for a specific host's info func (ipam *IPAMSvc) addVm(input interface{}, ctx common.RestContext) (interface{}, error) { vm := input.(*Vm) err := ipam.store.addVm(ipam.dc.EndpointSpaceBits, vm) if err != nil { return nil, err } client, err := common.NewRestClient("", ipam.config.Common.Api.RestTimeoutMillis) if err != nil { return nil, err } // Get host info from topology service topoUrl, err := client.GetServiceUrl(ipam.config.Common.Api.RootServiceUrl, "topology") if err != nil { return nil, err } index := common.IndexResponse{} err = client.Get(topoUrl, &index) if err != nil { return nil, err } hostsUrl := index.Links.FindByRel("host-list") host := common.HostMessage{} hostInfoUrl := fmt.Sprintf("%s/%s", hostsUrl, vm.HostId) err = client.Get(hostInfoUrl, &host) if err != nil { return nil, err } tenantUrl, err := client.GetServiceUrl(ipam.config.Common.Api.RootServiceUrl, "tenant") if err != nil { return nil, err } // TODO follow links once tenant service supports it. For now... t := &tenant.Tenant{} tenantsUrl := fmt.Sprintf("%s/tenants/%s", tenantUrl, vm.TenantId) log.Printf("IPAM calling %s\n", tenantsUrl) err = client.Get(tenantsUrl, t) if err != nil { return nil, err } log.Printf("IPAM received tenant %s ID %d\n", t.Name, t.Id) segmentUrl := fmt.Sprintf("/tenants/%s/segments/%s", vm.TenantId, vm.SegmentId) log.Printf("IPAM calling %s\n", segmentUrl) segment := &tenant.Segment{} err = client.Get(segmentUrl, segment) if err != nil { return nil, err } log.Printf("Constructing IP from Host IP %s, Tenant %d, Segment %d", host.RomanaIp, t.Seq, segment.Seq) vmBits := 32 - ipam.dc.PrefixBits - ipam.dc.PortBits - ipam.dc.TenantBits - ipam.dc.SegmentBits - ipam.dc.EndpointSpaceBits segmentBitShift := vmBits prefixBitShift := 32 - ipam.dc.PrefixBits tenantBitShift := segmentBitShift + ipam.dc.SegmentBits // hostBitShift := tenantBitShift + ipam.dc.TenantBits log.Printf("Parsing Romana IP address of host %s: %s\n", host.Name, host.RomanaIp) hostIp, _, err := net.ParseCIDR(host.RomanaIp) if err != nil { return nil, err } hostIpInt := common.IPv4ToInt(hostIp) vmIpInt := (ipam.dc.Prefix << prefixBitShift) | hostIpInt | (t.Seq << tenantBitShift) | (segment.Seq << segmentBitShift) | vm.EffectiveSeq vmIpIp := common.IntToIPv4(vmIpInt) log.Printf("Constructing (%d << %d) | %d | (%d << %d) | ( %d << %d ) | %d=%s\n", ipam.dc.Prefix, prefixBitShift, hostIpInt, t.Seq, tenantBitShift, segment.Seq, segmentBitShift, vm.EffectiveSeq, vmIpIp.String()) vm.Ip = vmIpIp.String() return vm, nil }
// 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") }