Пример #1
0
// flushGlobalPorts opens and closes global ports in the environment.
// It keeps a reference count for ports so that only 0-to-1 and 1-to-0 events
// modify the environment.
func (fw *Firewaller) flushGlobalPorts(rawOpen, rawClose []network.Port) error {
	// Filter which ports are really to open or close.
	var toOpen, toClose []network.Port
	for _, port := range rawOpen {
		if fw.globalPortRef[port] == 0 {
			toOpen = append(toOpen, port)
		}
		fw.globalPortRef[port]++
	}
	for _, port := range rawClose {
		fw.globalPortRef[port]--
		if fw.globalPortRef[port] == 0 {
			toClose = append(toClose, port)
			delete(fw.globalPortRef, port)
		}
	}
	// Open and close the ports.
	if len(toOpen) > 0 {
		if err := fw.environ.OpenPorts(toOpen); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		network.SortPorts(toOpen)
		logger.Infof("opened ports %v in environment", toOpen)
	}
	if len(toClose) > 0 {
		if err := fw.environ.ClosePorts(toClose); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		network.SortPorts(toClose)
		logger.Infof("closed ports %v in environment", toClose)
	}
	return nil
}
Пример #2
0
// reconcileInstances compares the initially started watcher for machines,
// units and services with the opened and closed ports of the instances and
// opens and closes the appropriate ports for each instance.
func (fw *Firewaller) reconcileInstances() error {
	for _, machined := range fw.machineds {
		m, err := machined.machine()
		if params.IsCodeNotFound(err) {
			if err := fw.forgetMachine(machined); err != nil {
				return err
			}
			continue
		} else if err != nil {
			return err
		}
		instanceId, err := m.InstanceId()
		if err != nil {
			return err
		}
		instances, err := fw.environ.Instances([]instance.Id{instanceId})
		if err == environs.ErrNoInstances {
			return nil
		} else if err != nil {
			return err
		}
		tag, err := names.ParseTag(machined.tag, names.MachineTagKind)
		if err != nil {
			return err
		}
		machineId := tag.Id()
		initialPorts, err := instances[0].Ports(machineId)
		if err != nil {
			return err
		}
		// Check which ports to open or to close.
		toOpen := Diff(machined.ports, initialPorts)
		toClose := Diff(initialPorts, machined.ports)
		if len(toOpen) > 0 {
			logger.Infof("opening instance ports %v for %q",
				toOpen, machined.tag)
			if err := instances[0].OpenPorts(machineId, toOpen); err != nil {
				// TODO(mue) Add local retry logic.
				return err
			}
			network.SortPorts(toOpen)
		}
		if len(toClose) > 0 {
			logger.Infof("closing instance ports %v for %q",
				toClose, machined.tag)
			if err := instances[0].ClosePorts(machineId, toClose); err != nil {
				// TODO(mue) Add local retry logic.
				return err
			}
			network.SortPorts(toClose)
		}
	}
	return nil
}
Пример #3
0
// flushInstancePorts opens and closes ports global on the machine.
func (fw *Firewaller) flushInstancePorts(machined *machineData, toOpen, toClose []network.Port) error {
	// If there's nothing to do, do nothing.
	// This is important because when a machine is first created,
	// it will have no instance id but also no open ports -
	// InstanceId will fail but we don't care.
	if len(toOpen) == 0 && len(toClose) == 0 {
		return nil
	}
	m, err := machined.machine()
	if params.IsCodeNotFound(err) {
		return nil
	}
	if err != nil {
		return err
	}
	tag, err := names.ParseTag(machined.tag, names.MachineTagKind)
	if err != nil {
		return err
	}
	machineId := tag.Id()
	instanceId, err := m.InstanceId()
	if err != nil {
		return err
	}
	instances, err := fw.environ.Instances([]instance.Id{instanceId})
	if err != nil {
		return err
	}
	// Open and close the ports.
	if len(toOpen) > 0 {
		if err := instances[0].OpenPorts(machineId, toOpen); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		network.SortPorts(toOpen)
		logger.Infof("opened ports %v on %q", toOpen, machined.tag)
	}
	if len(toClose) > 0 {
		if err := instances[0].ClosePorts(machineId, toClose); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		network.SortPorts(toClose)
		logger.Infof("closed ports %v on %q", toClose, machined.tag)
	}
	return nil
}
Пример #4
0
// Ports is specified in the Instance interface.
func (azInstance *azureInstance) Ports(machineId string) (ports []network.Port, err error) {
	err = azInstance.apiCall(false, func(context *azureManagementContext) error {
		ports, err = azInstance.listPorts(context)
		return err
	})
	if ports != nil {
		network.SortPorts(ports)
	}
	return ports, err
}
Пример #5
0
// assertEnvironPorts retrieves the open ports of environment and compares them
// to the expected.
func (s *FirewallerSuite) assertEnvironPorts(c *gc.C, expected []network.Port) {
	s.BackingState.StartSync()
	start := time.Now()
	for {
		got, err := s.Environ.Ports()
		if err != nil {
			c.Fatal(err)
			return
		}
		network.SortPorts(got)
		network.SortPorts(expected)
		if reflect.DeepEqual(got, expected) {
			c.Succeed()
			return
		}
		if time.Since(start) > coretesting.LongWait {
			c.Fatalf("timed out: expected %q; got %q", expected, got)
			return
		}
		time.Sleep(coretesting.ShortWait)
	}
}
Пример #6
0
func (s *instanceSuite) testPorts(c *gc.C, maskStateServerPorts bool) {
	// Update the role's endpoints by hand.
	configSetNetwork(s.role).InputEndpoints = &[]gwacl.InputEndpoint{{
		LocalPort: 223,
		Protocol:  "udp",
		Name:      "test223",
		Port:      2123,
	}, {
		LocalPort: 123,
		Protocol:  "udp",
		Name:      "test123",
		Port:      1123,
	}, {
		LocalPort: 456,
		Protocol:  "tcp",
		Name:      "test456",
		Port:      4456,
	}, {
		LocalPort: s.env.Config().StatePort(),
		Protocol:  "tcp",
		Name:      "stateserver",
		Port:      s.env.Config().StatePort(),
	}, {
		LocalPort: s.env.Config().APIPort(),
		Protocol:  "tcp",
		Name:      "apiserver",
		Port:      s.env.Config().APIPort(),
	}}

	responses := preparePortChangeConversation(c, s.role)
	record := gwacl.PatchManagementAPIResponses(responses)
	s.instance.maskStateServerPorts = maskStateServerPorts
	ports, err := s.instance.Ports("machine-id")
	c.Assert(err, gc.IsNil)
	assertPortChangeConversation(c, *record, []expectedRequest{
		{"GET", ".*/deployments/deployment-one/roles/role-one"}, // GetRole
	})

	expected := []network.Port{
		{Number: 4456, Protocol: "tcp"},
		{Number: 1123, Protocol: "udp"},
		{Number: 2123, Protocol: "udp"},
	}
	if !maskStateServerPorts {
		expected = append(expected, network.Port{Number: s.env.Config().StatePort(), Protocol: "tcp"})
		expected = append(expected, network.Port{Number: s.env.Config().APIPort(), Protocol: "tcp"})
		network.SortPorts(expected)
	}
	c.Check(ports, gc.DeepEquals, expected)
}
Пример #7
0
// reconcileGlobal compares the initially started watcher for machines,
// units and services with the opened and closed ports globally and
// opens and closes the appropriate ports for the whole environment.
func (fw *Firewaller) reconcileGlobal() error {
	initialPortRanges, err := fw.environ.Ports()
	if err != nil {
		return err
	}
	initialPorts := network.PortRangesToPorts(initialPortRanges)
	collector := make(map[network.Port]bool)
	for _, unitd := range fw.unitds {
		if unitd.serviced.exposed {
			for _, port := range unitd.ports {
				collector[port] = true
			}
		}
	}
	wantedPorts := []network.Port{}
	for port := range collector {
		wantedPorts = append(wantedPorts, port)
	}
	// Check which ports to open or to close.
	toOpen := Diff(wantedPorts, initialPorts)
	toClose := Diff(initialPorts, wantedPorts)
	if len(toOpen) > 0 {
		logger.Infof("opening global ports %v", toOpen)
		if err := fw.environ.OpenPorts(network.PortsToPortRanges(toOpen)); err != nil {
			return err
		}
		network.SortPorts(toOpen)
	}
	if len(toClose) > 0 {
		logger.Infof("closing global ports %v", toClose)
		if err := fw.environ.ClosePorts(network.PortsToPortRanges(toClose)); err != nil {
			return err
		}
		network.SortPorts(toClose)
	}
	return nil
}
Пример #8
0
// Helper method to get port from the given firewall rules
func getPorts(env *joyentEnviron, rules []cloudapi.FirewallRule) []network.Port {
	ports := []network.Port{}
	for _, r := range rules {
		rule := r.Rule
		if r.Enabled && strings.HasPrefix(rule, "FROM tag "+env.Name()) && strings.Contains(rule, "PORT") {
			p := rule[strings.Index(rule, "ALLOW")+6 : strings.Index(rule, "PORT")-1]
			n, _ := strconv.Atoi(rule[strings.LastIndex(rule, " ")+1:])
			port := network.Port{Protocol: p, Number: n}
			ports = append(ports, port)
		}
	}

	network.SortPorts(ports)
	return ports
}
Пример #9
0
func (e *environ) Ports() (ports []network.Port, err error) {
	if mode := e.ecfg().FirewallMode(); mode != config.FwGlobal {
		return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from environment", mode)
	}
	estate, err := e.state()
	if err != nil {
		return nil, err
	}
	estate.mu.Lock()
	defer estate.mu.Unlock()
	for p := range estate.globalPorts {
		ports = append(ports, p)
	}
	network.SortPorts(ports)
	return
}
Пример #10
0
func (inst *dummyInstance) Ports(machineId string) (ports []network.Port, err error) {
	defer delay()
	if inst.firewallMode != config.FwInstance {
		return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from instance",
			inst.firewallMode)
	}
	if inst.machineId != machineId {
		panic(fmt.Errorf("Ports with mismatched machine id, expected %q got %q", inst.machineId, machineId))
	}
	inst.state.mu.Lock()
	defer inst.state.mu.Unlock()
	for p := range inst.ports {
		ports = append(ports, p)
	}
	network.SortPorts(ports)
	return
}
Пример #11
0
// OpenedPorts returns a slice containing the open ports of the unit.
func (u *Unit) OpenedPorts() []network.Port {
	ports := append([]network.Port{}, u.doc.Ports...)
	network.SortPorts(ports)
	return ports
}