func TestRequiredCreateOpts(t *testing.T) { res := subnets.Create(fake.ServiceClient(), subnets.CreateOpts{}) if res.Err == nil { t.Fatalf("Expected error, got none") } res = subnets.Create(fake.ServiceClient(), subnets.CreateOpts{NetworkID: "foo"}) if res.Err == nil { t.Fatalf("Expected error, got none") } res = subnets.Create(fake.ServiceClient(), subnets.CreateOpts{NetworkID: "foo", CIDR: "bar", IPVersion: 40}) if res.Err == nil { t.Fatalf("Expected error, got none") } }
// CreateSubnetWithNoGateway will create a subnet with no gateway on the // specified Network ID. An error will be returned if the subnet could not be // created. func CreateSubnetWithNoGateway(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { var noGateway = "" subnetName := tools.RandomString("TESTACC-", 8) subnetOctet := tools.RandomInt(1, 250) subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) dhcpStart := fmt.Sprintf("192.168.%d.10", subnetOctet) dhcpEnd := fmt.Sprintf("192.168.%d.200", subnetOctet) createOpts := subnets.CreateOpts{ NetworkID: networkID, CIDR: subnetCIDR, IPVersion: 4, Name: subnetName, EnableDHCP: gophercloud.Disabled, GatewayIP: &noGateway, AllocationPools: []subnets.AllocationPool{ { Start: dhcpStart, End: dhcpEnd, }, }, } t.Logf("Attempting to create subnet: %s", subnetName) subnet, err := subnets.Create(client, createOpts).Extract() if err != nil { return subnet, err } t.Logf("Successfully created subnet.") return subnet, nil }
// CreateSubnetWithDefaultGateway will create a subnet on the specified Network // ID and have Neutron set the gateway by default An error will be returned if // the subnet could not be created. func CreateSubnetWithDefaultGateway(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { subnetName := tools.RandomString("TESTACC-", 8) subnetOctet := tools.RandomInt(1, 250) subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) createOpts := subnets.CreateOpts{ NetworkID: networkID, CIDR: subnetCIDR, IPVersion: 4, Name: subnetName, EnableDHCP: gophercloud.Disabled, } t.Logf("Attempting to create subnet: %s", subnetName) subnet, err := subnets.Create(client, createOpts).Extract() if err != nil { return subnet, err } t.Logf("Successfully created subnet.") return subnet, nil }
// deploy achieves the aims of Deploy(). func (p *openstackp) deploy(resources *Resources, requiredPorts []int) (err error) { // the resource name can only contain letters, numbers, underscores, // spaces and hyphens if !openstackValidResourceNameRegexp.MatchString(resources.ResourceName) { err = Error{"openstack", "deploy", ErrBadResourceName} return } // get/create key pair kp, err := keypairs.Get(p.computeClient, resources.ResourceName).Extract() if err != nil { if _, notfound := err.(gophercloud.ErrDefault404); notfound { // create a new keypair; we can't just let Openstack create one for // us because in latest versions it does not return a DER encoded // key, which is what GO built-in library supports. privateKey, errk := rsa.GenerateKey(rand.Reader, 1024) if errk != nil { err = errk return } privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} privateKeyPEMBytes := pem.EncodeToMemory(privateKeyPEM) pub, errk := ssh.NewPublicKey(&privateKey.PublicKey) if errk != nil { err = errk return err } publicKeyStr := ssh.MarshalAuthorizedKey(pub) kp, err = keypairs.Create(p.computeClient, keypairs.CreateOpts{Name: resources.ResourceName, PublicKey: string(publicKeyStr)}).Extract() if err != nil { return } resources.PrivateKey = string(privateKeyPEMBytes) } else { return } } resources.Details["keypair"] = kp.Name // based on hostname, see if we're currently running on an openstack server, // in which case we'll use this server's security group and network. hostname, err := os.Hostname() inCloud := false if err == nil { pager := servers.List(p.computeClient, servers.ListOpts{}) err = pager.EachPage(func(page pagination.Page) (bool, error) { serverList, err := servers.ExtractServers(page) if err != nil { return false, err } for _, server := range serverList { if server.Name == hostname { p.ownName = hostname // get the first networkUUID we come across *** not sure // what the other possibilities are and what else we can do // instead for networkName := range server.Addresses { networkUUID, _ := networks.IDFromName(p.networkClient, networkName) if networkUUID != "" { p.networkName = networkName p.networkUUID = networkUUID break } } // get the first security group *** again, not sure how to // pick the "best" if more than one for _, smap := range server.SecurityGroups { if value, found := smap["name"]; found && value.(string) != "" { p.securityGroup = value.(string) break } } if p.networkUUID != "" && p.securityGroup != "" { inCloud = true return false, nil } } } return true, nil }) } //*** actually, if in cloud, we should create a security group that allows // the given ports, only accessible by things in the current security group // don't create any more resources if we're already running in OpenStack if inCloud { return } // get/create security group pager := secgroups.List(p.computeClient) var group *secgroups.SecurityGroup foundGroup := false err = pager.EachPage(func(page pagination.Page) (bool, error) { groupList, err := secgroups.ExtractSecurityGroups(page) if err != nil { return false, err } for _, g := range groupList { if g.Name == resources.ResourceName { group = &g foundGroup = true return false, nil } } return true, nil }) if err != nil { return } if !foundGroup { // create a new security group with rules allowing the desired ports group, err = secgroups.Create(p.computeClient, secgroups.CreateOpts{Name: resources.ResourceName, Description: "access amongst wr-spawned nodes"}).Extract() if err != nil { return } //*** check if the rules are already there, in case we previously died // between previous line and this one for _, port := range requiredPorts { _, err = secgroups.CreateRule(p.computeClient, secgroups.CreateRuleOpts{ ParentGroupID: group.ID, FromPort: port, ToPort: port, IPProtocol: "TCP", CIDR: "0.0.0.0/0", // FromGroupID: group.ID if we were creating a head node and then wanted a rule for all worker nodes... }).Extract() if err != nil { return } } // ICMP may help networking work as expected _, err = secgroups.CreateRule(p.computeClient, secgroups.CreateRuleOpts{ ParentGroupID: group.ID, FromPort: 0, ToPort: 0, // *** results in a port of '0', which is not the same as "ALL ICMP" which then says "Any" in the web interface IPProtocol: "ICMP", CIDR: "0.0.0.0/0", }).Extract() if err != nil { return } } resources.Details["secgroup"] = group.ID p.securityGroup = resources.ResourceName // get/create network var network *networks.Network networkID, err := networks.IDFromName(p.networkClient, resources.ResourceName) if err != nil { if _, notfound := err.(gophercloud.ErrResourceNotFound); notfound { // create a network for ourselves network, err = networks.Create(p.networkClient, networks.CreateOpts{Name: resources.ResourceName, AdminStateUp: gophercloud.Enabled}).Extract() if err != nil { return } networkID = network.ID } else { return } } else { network, err = networks.Get(p.networkClient, networkID).Extract() if err != nil { return } } resources.Details["network"] = networkID p.networkName = resources.ResourceName p.networkUUID = networkID // get/create subnet var subnetID string if len(network.Subnets) == 1 { subnetID = network.Subnets[0] // *** check it's valid? could we end up with more than 1 subnet? } else { // add a big enough subnet var gip = new(string) *gip = "192.168.0.1" var subnet *subnets.Subnet subnet, err = subnets.Create(p.networkClient, subnets.CreateOpts{ NetworkID: networkID, CIDR: "192.168.0.0/16", GatewayIP: gip, DNSNameservers: dnsNameServers[:], // this is critical, or servers on new networks can't be ssh'd to for many minutes IPVersion: 4, Name: resources.ResourceName, }).Extract() if err != nil { return } subnetID = subnet.ID } resources.Details["subnet"] = subnetID // get/create router var routerID string pager = routers.List(p.networkClient, routers.ListOpts{Name: resources.ResourceName}) err = pager.EachPage(func(page pagination.Page) (bool, error) { routerList, err := routers.ExtractRouters(page) if err != nil { return false, err } routerID = routerList[0].ID // *** check it's valid? could we end up with more than 1 router? return false, nil }) if err != nil { return } if routerID == "" { var router *routers.Router router, err = routers.Create(p.networkClient, routers.CreateOpts{ Name: resources.ResourceName, GatewayInfo: &routers.GatewayInfo{NetworkID: p.externalNetworkID}, AdminStateUp: gophercloud.Enabled, }).Extract() if err != nil { return } routerID = router.ID // add our subnet _, err = routers.AddInterface(p.networkClient, routerID, routers.AddInterfaceOpts{SubnetID: subnetID}).Extract() if err != nil { // if this fails, we'd be stuck with a useless router, so we try and // delete it routers.Delete(p.networkClient, router.ID) return } } resources.Details["router"] = routerID return }
func TestNeutron(t *testing.T) { authUrl := os.Getenv("OS_AUTH_URL") username := os.Getenv("OS_USERNAME") password := os.Getenv("OS_PASSWORD") tenantName := os.Getenv("OS_TENANT_NAME") regionName := os.Getenv("OS_REGION_NAME") opts := gophercloud.AuthOptions{ IdentityEndpoint: authUrl, Username: username, Password: password, TenantName: tenantName, } provider, err := openstack.AuthenticatedClient(opts) if err != nil { t.Fatal(err.Error()) } client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ Name: "neutron", Region: regionName, Availability: gophercloud.AvailabilityPublic, }) if err != nil { t.Fatalf("Failed to create neutron client: %s", err.Error()) } netResult := networks.Create(client, networks.CreateOpts{Name: "skydive-test-network"}) if netResult.Err != nil { t.Fatalf("Failed to create neutron network: %s", netResult.Err.Error()) } network, err := netResult.Extract() if err != nil { t.Fatalf("Failed to create neutron network: %s", err.Error()) } subResult := subnets.Create(client, subnets.CreateOpts{Name: "skydive-test-subnet", NetworkID: network.ID, CIDR: "192.168.1.0/24", IPVersion: 4}) if subResult.Err != nil { t.Fatalf("Failed to create neutron subnet: %s", subResult.Err.Error()) } subnet, err := subResult.Extract() if err != nil { t.Fatalf("Failed to create neutron subnet: %s", err.Error()) } portResult := ports.Create(client, ports.CreateOpts{NetworkID: network.ID, DeviceID: "skydive-123", DeviceOwner: "skydive-test"}) if portResult.Err != nil { t.Fatalf("Failed to create neutron port: %s", subResult.Err.Error()) } port, err := portResult.Extract() if err != nil { t.Fatalf("Failed to create neutron port: %s", err.Error()) } defer ports.Delete(client, port.ID) defer subnets.Delete(client, subnet.ID) defer networks.Delete(client, network.ID) authOptions := &shttp.AuthenticationOpts{ Username: username, Password: password, } subID := port.ID[0:11] dev := fmt.Sprintf("tap%s", subID) ovsctl := `ovs-vsctl add-port br-int %s -- set Interface %s external-ids:iface-id=%s` ovsctl += ` external-ids:iface-status=active external-ids:attached-mac=%s external-ids:vm-uuid=skydive-vm type=internal` setupCmds := []helper.Cmd{ {fmt.Sprintf(ovsctl, dev, dev, port.ID, port.MACAddress), true}, {"sleep 1", true}, {fmt.Sprintf("ip link set %s up", dev), true}, } tearDownCmds := []helper.Cmd{ {fmt.Sprintf("ovs-vsctl del-port %s", dev), true}, } helper.ExecCmds(t, setupCmds...) defer helper.ExecCmds(t, tearDownCmds...) gh := helper.NewGremlinQueryHelper(authOptions) // let neutron update the port time.Sleep(5 * time.Second) nodes := gh.GetNodesFromGremlinReply(t, `g.V().Has("Manager", "neutron", "ExtID/vm-uuid", "skydive-vm", "Name", "`+dev+`", "Neutron/PortID", "`+port.ID+`")`) if len(nodes) != 1 { t.Errorf("Should find the neutron port in the topology: %v", gh.GetNodesFromGremlinReply(t, `g.V()`)) } }
func resourceNetworkingSubnetV2Create(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) networkingClient, err := config.networkingV2Client(d.Get("region").(string)) if err != nil { return fmt.Errorf("Error creating OpenStack networking client: %s", err) } createOpts := SubnetCreateOpts{ subnets.CreateOpts{ NetworkID: d.Get("network_id").(string), CIDR: d.Get("cidr").(string), Name: d.Get("name").(string), TenantID: d.Get("tenant_id").(string), AllocationPools: resourceSubnetAllocationPoolsV2(d), DNSNameservers: resourceSubnetDNSNameserversV2(d), HostRoutes: resourceSubnetHostRoutesV2(d), EnableDHCP: nil, }, MapValueSpecs(d), } noGateway := d.Get("no_gateway").(bool) gatewayIP := d.Get("gateway_ip").(string) if gatewayIP != "" && noGateway { return fmt.Errorf("Both gateway_ip and no_gateway cannot be set") } if gatewayIP != "" { createOpts.GatewayIP = &gatewayIP } if noGateway { disableGateway := "" createOpts.GatewayIP = &disableGateway } enableDHCP := d.Get("enable_dhcp").(bool) createOpts.EnableDHCP = &enableDHCP if v, ok := d.GetOk("ip_version"); ok { ipVersion := resourceNetworkingSubnetV2DetermineIPVersion(v.(int)) createOpts.IPVersion = ipVersion } s, err := subnets.Create(networkingClient, createOpts).Extract() if err != nil { return fmt.Errorf("Error creating OpenStack Neutron subnet: %s", err) } log.Printf("[DEBUG] Waiting for Subnet (%s) to become available", s.ID) stateConf := &resource.StateChangeConf{ Target: []string{"ACTIVE"}, Refresh: waitForSubnetActive(networkingClient, s.ID), Timeout: 10 * time.Minute, Delay: 5 * time.Second, MinTimeout: 3 * time.Second, } _, err = stateConf.WaitForState() d.SetId(s.ID) log.Printf("[DEBUG] Created Subnet %s: %#v", s.ID, s) return resourceNetworkingSubnetV2Read(d, meta) }
func TestCreateDefaultGateway(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() th.Mux.HandleFunc("/v2.0/subnets", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "POST") th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) th.TestHeader(t, r, "Content-Type", "application/json") th.TestHeader(t, r, "Accept", "application/json") th.TestJSONRequest(t, r, ` { "subnet": { "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", "ip_version": 4, "cidr": "192.168.1.0/24", "allocation_pools": [ { "start": "192.168.1.2", "end": "192.168.1.254" } ] } } `) w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) fmt.Fprintf(w, ` { "subnet": { "name": "", "enable_dhcp": true, "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "allocation_pools": [ { "start": "192.168.1.2", "end": "192.168.1.254" } ], "host_routes": [], "ip_version": 4, "gateway_ip": "192.168.1.1", "cidr": "192.168.1.0/24", "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" } } `) }) opts := subnets.CreateOpts{ NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a23", IPVersion: 4, CIDR: "192.168.1.0/24", AllocationPools: []subnets.AllocationPool{ { Start: "192.168.1.2", End: "192.168.1.254", }, }, DNSNameservers: []string{}, } s, err := subnets.Create(fake.ServiceClient(), opts).Extract() th.AssertNoErr(t, err) th.AssertEquals(t, s.Name, "") th.AssertEquals(t, s.EnableDHCP, true) th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a23") th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869") th.AssertDeepEquals(t, s.AllocationPools, []subnets.AllocationPool{ { Start: "192.168.1.2", End: "192.168.1.254", }, }) th.AssertDeepEquals(t, s.HostRoutes, []subnets.HostRoute{}) th.AssertEquals(t, s.IPVersion, 4) th.AssertEquals(t, s.GatewayIP, "192.168.1.1") th.AssertEquals(t, s.CIDR, "192.168.1.0/24") th.AssertEquals(t, s.ID, "54d6f61d-db07-451c-9ab3-b9609b6b6f0c") }
// Create network func (os *OpenStack) CreateNetwork(network *provider.Network) error { if len(network.Subnets) == 0 { return errors.New("Subnets is null") } // create network opts := networks.CreateOpts{ Name: network.Name, AdminStateUp: &adminStateUp, TenantID: network.TenantID, } osNet, err := networks.Create(os.network, opts).Extract() if err != nil { glog.Errorf("Create openstack network %s failed: %v", network.Name, err) return err } // create router routerOpts := routers.CreateOpts{ Name: network.Name, TenantID: network.TenantID, GatewayInfo: &routers.GatewayInfo{NetworkID: os.ExtNetID}, } osRouter, err := routers.Create(os.network, routerOpts).Extract() if err != nil { glog.Errorf("Create openstack router %s failed: %v", network.Name, err) delErr := os.DeleteNetwork(network.Name) if delErr != nil { glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr) } return err } // create subnets and connect them to router networkID := osNet.ID network.Status = os.ToProviderStatus(osNet.Status) network.Uid = osNet.ID for _, sub := range network.Subnets { // create subnet subnetOpts := subnets.CreateOpts{ NetworkID: networkID, CIDR: sub.Cidr, Name: sub.Name, IPVersion: gophercloud.IPv4, TenantID: network.TenantID, GatewayIP: &sub.Gateway, DNSNameservers: sub.Dnsservers, } s, err := subnets.Create(os.network, subnetOpts).Extract() if err != nil { glog.Errorf("Create openstack subnet %s failed: %v", sub.Name, err) delErr := os.DeleteNetwork(network.Name) if delErr != nil { glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr) } return err } // add subnet to router opts := routers.AddInterfaceOpts{ SubnetID: s.ID, } _, err = routers.AddInterface(os.network, osRouter.ID, opts).Extract() if err != nil { glog.Errorf("Create openstack subnet %s failed: %v", sub.Name, err) delErr := os.DeleteNetwork(network.Name) if delErr != nil { glog.Errorf("Delete openstack network %s failed: %v", network.Name, delErr) } return err } } return nil }