Example #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 []instance.Port) error {
	// Filter which ports are really to open or close.
	var toOpen, toClose []instance.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
		}
		state.SortPorts(toOpen)
		log.Infof("worker/firewaller: 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
		}
		state.SortPorts(toClose)
		log.Infof("worker/firewaller: closed ports %v in environment", toClose)
	}
	return nil
}
Example #2
0
func (*StateSuite) TestSortPorts(c *C) {
	for _, t := range sortPortsTests {
		p := make([]state.Port, len(t.have))
		copy(p, t.have)
		state.SortPorts(p)
		c.Check(p, DeepEquals, t.want)
		state.SortPorts(p)
		c.Check(p, DeepEquals, t.want)
	}
}
Example #3
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 errors.IsNotFoundError(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
		}
		initialPorts, err := instances[0].Ports(machined.id)
		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 {
			log.Infof("worker/firewaller: opening instance ports %v for machine %s",
				toOpen, machined.id)
			if err := instances[0].OpenPorts(machined.id, toOpen); err != nil {
				// TODO(mue) Add local retry logic.
				return err
			}
			state.SortPorts(toOpen)
		}
		if len(toClose) > 0 {
			log.Infof("worker/firewaller: closing instance ports %v for machine %s",
				toClose, machined.id)
			if err := instances[0].ClosePorts(machined.id, toClose); err != nil {
				// TODO(mue) Add local retry logic.
				return err
			}
			state.SortPorts(toClose)
		}
	}
	return nil
}
Example #4
0
// flushGlobalPorts opens and closes ports global on the machine.
func (fw *Firewaller) flushInstancePorts(machined *machineData, toOpen, toClose []instance.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 errors.IsNotFoundError(err) {
		return nil
	}
	if err != nil {
		return err
	}
	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(machined.id, toOpen); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		state.SortPorts(toOpen)
		log.Infof("worker/firewaller: opened ports %v on machine %s", toOpen, machined.id)
	}
	if len(toClose) > 0 {
		if err := instances[0].ClosePorts(machined.id, toClose); err != nil {
			// TODO(mue) Add local retry logic.
			return err
		}
		state.SortPorts(toClose)
		log.Infof("worker/firewaller: closed ports %v on machine %s", toClose, machined.id)
	}
	return nil
}
Example #5
0
// assertEnvironPorts retrieves the open ports of environment and compares them
// to the expected.
func (s *FirewallerSuite) assertEnvironPorts(c *C, expected []instance.Port) {
	s.State.StartSync()
	start := time.Now()
	for {
		got, err := s.Conn.Environ.Ports()
		if err != nil {
			c.Fatal(err)
			return
		}
		state.SortPorts(got)
		state.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)
	}
}
Example #6
0
func (e *environ) Ports() (ports []instance.Port, err error) {
	e.state.mu.Lock()
	defer e.state.mu.Unlock()
	if e.state.firewallMode != config.FwGlobal {
		return nil, fmt.Errorf("invalid firewall mode for retrieving ports from environment: %q",
			e.state.firewallMode)
	}
	for p := range e.state.globalPorts {
		ports = append(ports, p)
	}
	state.SortPorts(ports)
	return
}
Example #7
0
// assertEnvironPorts retrieves the open ports of environment and compares them
// to the expected.
func (s *FirewallerSuite) assertEnvironPorts(c *C, expected []state.Port) {
	s.State.StartSync()
	start := time.Now()
	for {
		got, err := s.Conn.Environ.Ports()
		if err != nil {
			c.Fatal(err)
			return
		}
		state.SortPorts(got)
		state.SortPorts(expected)
		if reflect.DeepEqual(got, expected) {
			c.Succeed()
			return
		}
		if time.Since(start) > 5*time.Second {
			c.Fatalf("timed out: expected %q; got %q", expected, got)
			return
		}
		time.Sleep(50 * time.Millisecond)
	}
	panic("unreachable")
}
// assertPorts retrieves the open ports of the instance and compares them
// to the expected.
func (s *FirewallerSuite) assertPorts(c *C, inst instance.Instance, machineId string, expected []instance.Port) {
	s.State.StartSync()
	start := time.Now()
	for {
		got, err := inst.Ports(machineId)
		if err != nil {
			c.Fatal(err)
			return
		}
		state.SortPorts(got)
		state.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)
	}
	panic("unreachable")
}
Example #9
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 {
	initialPorts, err := fw.environ.Ports()
	if err != nil {
		return err
	}
	collector := make(map[instance.Port]bool)
	for _, unitd := range fw.unitds {
		if unitd.serviced.exposed {
			for _, port := range unitd.ports {
				collector[port] = true
			}
		}
	}
	wantedPorts := []instance.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 {
		log.Infof("worker/firewaller: opening global ports %v", toOpen)
		if err := fw.environ.OpenPorts(toOpen); err != nil {
			return err
		}
		state.SortPorts(toOpen)
	}
	if len(toClose) > 0 {
		log.Infof("worker/firewaller: closing global ports %v", toClose)
		if err := fw.environ.ClosePorts(toClose); err != nil {
			return err
		}
		state.SortPorts(toClose)
	}
	return nil
}
Example #10
0
// Ports is specified in the Instance interface.
func (azInstance *azureInstance) Ports(machineId string) ([]instance.Port, error) {
	env := azInstance.environ
	context, err := env.getManagementAPI()
	if err != nil {
		return nil, err
	}
	defer env.releaseManagementAPI(context)

	ports, err := azInstance.listPorts(context)
	if err != nil {
		return nil, err
	}
	state.SortPorts(ports)
	return ports, nil
}
Example #11
0
func (e *environ) portsInGroup(name string) (ports []instance.Port, err error) {
	group, err := e.nova().SecurityGroupByName(name)
	if err != nil {
		return nil, err
	}
	for _, p := range (*group).Rules {
		for i := *p.FromPort; i <= *p.ToPort; i++ {
			ports = append(ports, instance.Port{
				Protocol: *p.IPProtocol,
				Number:   i,
			})
		}
	}
	state.SortPorts(ports)
	return ports, nil
}
Example #12
0
func (inst *dummyInstance) Ports(machineId string) (ports []instance.Port, err error) {
	defer delay()
	if inst.state.firewallMode != config.FwInstance {
		return nil, fmt.Errorf("invalid firewall mode for retrieving ports from instance: %q",
			inst.state.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)
	}
	state.SortPorts(ports)
	return
}
Example #13
0
func (e *environ) portsInGroup(name string) (ports []instance.Port, err error) {
	g := ec2.SecurityGroup{Name: name}
	resp, err := e.ec2().SecurityGroups([]ec2.SecurityGroup{g}, nil)
	if err != nil {
		return nil, err
	}
	if len(resp.Groups) != 1 {
		return nil, fmt.Errorf("expected one security group, got %d", len(resp.Groups))
	}
	for _, p := range resp.Groups[0].IPPerms {
		if len(p.SourceIPs) != 1 {
			log.Warningf("environs/ec2: unexpected IP permission found: %v", p)
			continue
		}
		for i := p.FromPort; i <= p.ToPort; i++ {
			ports = append(ports, instance.Port{
				Protocol: p.Protocol,
				Number:   i,
			})
		}
	}
	state.SortPorts(ports)
	return ports, nil
}