github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/testing/stub_network.go (about)

     1  package testing
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/juju/juju/apiserver/common/networkingcommon"
    10  	"github.com/juju/juju/apiserver/params"
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/environs/config"
    13  	"github.com/juju/juju/instance"
    14  	"github.com/juju/juju/network"
    15  	providercommon "github.com/juju/juju/provider/common"
    16  	coretesting "github.com/juju/juju/testing"
    17  	"github.com/juju/testing"
    18  	"github.com/juju/utils"
    19  	"github.com/juju/utils/set"
    20  	gc "gopkg.in/check.v1"
    21  )
    22  
    23  type StubNetwork struct {
    24  }
    25  
    26  var (
    27  	// SharedStub records all method calls to any of the stubs.
    28  	SharedStub = &testing.Stub{}
    29  
    30  	BackingInstance                = &StubBacking{Stub: SharedStub}
    31  	ProviderInstance               = &StubProvider{Stub: SharedStub}
    32  	EnvironInstance                = &StubEnviron{Stub: SharedStub}
    33  	ZonedEnvironInstance           = &StubZonedEnviron{Stub: SharedStub}
    34  	NetworkingEnvironInstance      = &StubNetworkingEnviron{Stub: SharedStub}
    35  	ZonedNetworkingEnvironInstance = &StubZonedNetworkingEnviron{Stub: SharedStub}
    36  )
    37  
    38  const (
    39  	StubProviderType               = "stub-provider"
    40  	StubEnvironName                = "stub-environ"
    41  	StubZonedEnvironName           = "stub-zoned-environ"
    42  	StubNetworkingEnvironName      = "stub-networking-environ"
    43  	StubZonedNetworkingEnvironName = "stub-zoned-networking-environ"
    44  )
    45  
    46  func (s StubNetwork) SetUpSuite(c *gc.C) {
    47  	providers := environs.RegisteredProviders()
    48  	for _, name := range providers {
    49  		if name == StubProviderType {
    50  			return
    51  		}
    52  	}
    53  
    54  	ProviderInstance.Zones = []providercommon.AvailabilityZone{
    55  		&FakeZone{"zone1", true},
    56  		&FakeZone{"zone2", false},
    57  		&FakeZone{"zone3", true},
    58  		&FakeZone{"zone4", false},
    59  		&FakeZone{"zone4", false}, // duplicates are ignored
    60  	}
    61  	ProviderInstance.Subnets = []network.SubnetInfo{{
    62  		CIDR:              "10.10.0.0/24",
    63  		ProviderId:        "sn-zadf00d",
    64  		AvailabilityZones: []string{"zone1"},
    65  		AllocatableIPLow:  net.ParseIP("10.10.0.10"),
    66  		AllocatableIPHigh: net.ParseIP("10.10.0.100"),
    67  	}, {
    68  		CIDR:              "2001:db8::/32",
    69  		ProviderId:        "sn-ipv6",
    70  		AvailabilityZones: []string{"zone1", "zone3"},
    71  	}, {
    72  		// no CIDR or provider id -> cached, but cannot be added
    73  		CIDR:       "",
    74  		ProviderId: "",
    75  	}, {
    76  		// no CIDR, just provider id -> cached, but can only be added by id
    77  		CIDR:       "",
    78  		ProviderId: "sn-empty",
    79  	}, {
    80  		// invalid CIDR and provider id -> cannot be added, but is cached
    81  		CIDR:       "invalid",
    82  		ProviderId: "sn-invalid",
    83  	}, {
    84  		// incorrectly specified CIDR, with provider id -> cached, cannot be added
    85  		CIDR:       "0.1.2.3/4",
    86  		ProviderId: "sn-awesome",
    87  	}, {
    88  		// no zones, no provider-id -> cached, but can only be added by CIDR
    89  		CIDR: "10.20.0.0/16",
    90  	}, {
    91  		// with zones, duplicate provider-id -> overwritten by the last
    92  		// subnet with the same provider id when caching.
    93  		CIDR:              "10.99.88.0/24",
    94  		ProviderId:        "sn-deadbeef",
    95  		AvailabilityZones: []string{"zone1", "zone2"},
    96  	}, {
    97  		// no zones
    98  		CIDR:       "10.42.0.0/16",
    99  		ProviderId: "sn-42",
   100  	}, {
   101  		// in an unavailable zone, duplicate CIDR -> cannot be added, but is cached
   102  		CIDR:              "10.10.0.0/24",
   103  		ProviderId:        "sn-deadbeef",
   104  		AvailabilityZones: []string{"zone2"},
   105  	}, {
   106  		CIDR:              "10.30.1.0/24",
   107  		ProviderId:        "vlan-42",
   108  		VLANTag:           42,
   109  		AvailabilityZones: []string{"zone3"},
   110  	}}
   111  
   112  	environs.RegisterProvider(StubProviderType, ProviderInstance)
   113  }
   114  
   115  type errReturner func() error
   116  
   117  // FakeSpace implements networkingcommon.BackingSpace for testing.
   118  type FakeSpace struct {
   119  	SpaceName string
   120  	SubnetIds []string
   121  	Public    bool
   122  	NextErr   errReturner
   123  }
   124  
   125  var _ networkingcommon.BackingSpace = (*FakeSpace)(nil)
   126  
   127  func (f *FakeSpace) Name() string {
   128  	return f.SpaceName
   129  }
   130  
   131  func (f *FakeSpace) Subnets() (bs []networkingcommon.BackingSubnet, err error) {
   132  	outputSubnets := []networkingcommon.BackingSubnet{}
   133  
   134  	if err = f.NextErr(); err != nil {
   135  		return outputSubnets, err
   136  	}
   137  
   138  	for _, subnetId := range f.SubnetIds {
   139  		providerId := network.Id("provider-" + subnetId)
   140  
   141  		// Pick the third element of the IP address and use this to
   142  		// decide how we construct the Subnet. It provides variation of
   143  		// test data.
   144  		first, err := strconv.Atoi(strings.Split(subnetId, ".")[2])
   145  		if err != nil {
   146  			return outputSubnets, err
   147  		}
   148  		vlantag := 0
   149  		zones := []string{"foo"}
   150  		status := "in-use"
   151  		if first%2 == 1 {
   152  			vlantag = 23
   153  			zones = []string{"bar", "bam"}
   154  			status = ""
   155  		}
   156  
   157  		backing := networkingcommon.BackingSubnetInfo{
   158  			CIDR:              subnetId,
   159  			SpaceName:         f.SpaceName,
   160  			ProviderId:        providerId,
   161  			VLANTag:           vlantag,
   162  			AvailabilityZones: zones,
   163  			Status:            status,
   164  		}
   165  		outputSubnets = append(outputSubnets, &FakeSubnet{info: backing})
   166  	}
   167  
   168  	return outputSubnets, nil
   169  }
   170  
   171  func (f *FakeSpace) ProviderId() (netID network.Id) {
   172  	return
   173  }
   174  
   175  func (f *FakeSpace) Zones() []string {
   176  	return []string{""}
   177  }
   178  
   179  func (f *FakeSpace) Life() (life params.Life) {
   180  	return
   181  }
   182  
   183  // GoString implements fmt.GoStringer.
   184  func (f *FakeSpace) GoString() string {
   185  	return fmt.Sprintf("&FakeSpace{%q}", f.SpaceName)
   186  }
   187  
   188  // StubMethodCall is like testing.StubCall, but includes the receiver
   189  // as well.
   190  type StubMethodCall struct {
   191  	Receiver interface{}
   192  	FuncName string
   193  	Args     []interface{}
   194  }
   195  
   196  // BackingCall makes it easy to check method calls on BackingInstance.
   197  func BackingCall(name string, args ...interface{}) StubMethodCall {
   198  	return StubMethodCall{
   199  		Receiver: BackingInstance,
   200  		FuncName: name,
   201  		Args:     args,
   202  	}
   203  }
   204  
   205  // ProviderCall makes it easy to check method calls on ProviderInstance.
   206  func ProviderCall(name string, args ...interface{}) StubMethodCall {
   207  	return StubMethodCall{
   208  		Receiver: ProviderInstance,
   209  		FuncName: name,
   210  		Args:     args,
   211  	}
   212  }
   213  
   214  // EnvironCall makes it easy to check method calls on EnvironInstance.
   215  func EnvironCall(name string, args ...interface{}) StubMethodCall {
   216  	return StubMethodCall{
   217  		Receiver: EnvironInstance,
   218  		FuncName: name,
   219  		Args:     args,
   220  	}
   221  }
   222  
   223  // ZonedEnvironCall makes it easy to check method calls on
   224  // ZonedEnvironInstance.
   225  func ZonedEnvironCall(name string, args ...interface{}) StubMethodCall {
   226  	return StubMethodCall{
   227  		Receiver: ZonedEnvironInstance,
   228  		FuncName: name,
   229  		Args:     args,
   230  	}
   231  }
   232  
   233  // NetworkingEnvironCall makes it easy to check method calls on
   234  // NetworkingEnvironInstance.
   235  func NetworkingEnvironCall(name string, args ...interface{}) StubMethodCall {
   236  	return StubMethodCall{
   237  		Receiver: NetworkingEnvironInstance,
   238  		FuncName: name,
   239  		Args:     args,
   240  	}
   241  }
   242  
   243  // ZonedNetworkingEnvironCall makes it easy to check method calls on
   244  // ZonedNetworkingEnvironInstance.
   245  func ZonedNetworkingEnvironCall(name string, args ...interface{}) StubMethodCall {
   246  	return StubMethodCall{
   247  		Receiver: ZonedNetworkingEnvironInstance,
   248  		FuncName: name,
   249  		Args:     args,
   250  	}
   251  }
   252  
   253  // CheckMethodCalls works like testing.Stub.CheckCalls, but also
   254  // checks the receivers.
   255  func CheckMethodCalls(c *gc.C, stub *testing.Stub, calls ...StubMethodCall) {
   256  	receivers := make([]interface{}, len(calls))
   257  	for i, call := range calls {
   258  		receivers[i] = call.Receiver
   259  	}
   260  	stub.CheckReceivers(c, receivers...)
   261  	c.Check(stub.Calls(), gc.HasLen, len(calls))
   262  	for i, call := range calls {
   263  		stub.CheckCall(c, i, call.FuncName, call.Args...)
   264  	}
   265  }
   266  
   267  // FakeZone implements providercommon.AvailabilityZone for testing.
   268  type FakeZone struct {
   269  	ZoneName      string
   270  	ZoneAvailable bool
   271  }
   272  
   273  var _ providercommon.AvailabilityZone = (*FakeZone)(nil)
   274  
   275  func (f *FakeZone) Name() string {
   276  	return f.ZoneName
   277  }
   278  
   279  func (f *FakeZone) Available() bool {
   280  	return f.ZoneAvailable
   281  }
   282  
   283  // GoString implements fmt.GoStringer.
   284  func (f *FakeZone) GoString() string {
   285  	return fmt.Sprintf("&FakeZone{%q, %v}", f.ZoneName, f.ZoneAvailable)
   286  }
   287  
   288  // FakeSubnet implements networkingcommon.BackingSubnet for testing.
   289  type FakeSubnet struct {
   290  	info networkingcommon.BackingSubnetInfo
   291  }
   292  
   293  var _ networkingcommon.BackingSubnet = (*FakeSubnet)(nil)
   294  
   295  // GoString implements fmt.GoStringer.
   296  func (f *FakeSubnet) GoString() string {
   297  	return fmt.Sprintf("&FakeSubnet{%#v}", f.info)
   298  }
   299  
   300  func (f *FakeSubnet) Status() string {
   301  	return f.info.Status
   302  }
   303  
   304  func (f *FakeSubnet) CIDR() string {
   305  	return f.info.CIDR
   306  }
   307  
   308  func (f *FakeSubnet) AvailabilityZones() []string {
   309  	return f.info.AvailabilityZones
   310  }
   311  
   312  func (f *FakeSubnet) ProviderId() network.Id {
   313  	return f.info.ProviderId
   314  }
   315  
   316  func (f *FakeSubnet) VLANTag() int {
   317  	return f.info.VLANTag
   318  }
   319  
   320  func (f *FakeSubnet) SpaceName() string {
   321  	return f.info.SpaceName
   322  }
   323  
   324  func (f *FakeSubnet) Life() params.Life {
   325  	return f.info.Life
   326  }
   327  
   328  // ResetStub resets all recorded calls and errors of the given stub.
   329  func ResetStub(stub *testing.Stub) {
   330  	*stub = testing.Stub{}
   331  }
   332  
   333  // StubBacking implements networkingcommon.NetworkBacking and records calls to its
   334  // methods.
   335  type StubBacking struct {
   336  	*testing.Stub
   337  
   338  	EnvConfig *config.Config
   339  
   340  	Zones   []providercommon.AvailabilityZone
   341  	Spaces  []networkingcommon.BackingSpace
   342  	Subnets []networkingcommon.BackingSubnet
   343  }
   344  
   345  var _ networkingcommon.NetworkBacking = (*StubBacking)(nil)
   346  
   347  type SetUpFlag bool
   348  
   349  const (
   350  	WithZones      SetUpFlag = true
   351  	WithoutZones   SetUpFlag = false
   352  	WithSpaces     SetUpFlag = true
   353  	WithoutSpaces  SetUpFlag = false
   354  	WithSubnets    SetUpFlag = true
   355  	WithoutSubnets SetUpFlag = false
   356  )
   357  
   358  func (sb *StubBacking) SetUp(c *gc.C, envName string, withZones, withSpaces, withSubnets SetUpFlag) {
   359  	// This method must be called at the beginning of each test, which
   360  	// needs access to any of the mocks, to reset the recorded calls
   361  	// and errors, as well as to initialize the mocks as needed.
   362  	ResetStub(sb.Stub)
   363  
   364  	// Make sure we use the stub provider.
   365  	extraAttrs := coretesting.Attrs{
   366  		"uuid": utils.MustNewUUID().String(),
   367  		"type": StubProviderType,
   368  		"name": envName,
   369  	}
   370  	sb.EnvConfig = coretesting.CustomModelConfig(c, extraAttrs)
   371  	sb.Zones = []providercommon.AvailabilityZone{}
   372  	if withZones {
   373  		sb.Zones = make([]providercommon.AvailabilityZone, len(ProviderInstance.Zones))
   374  		copy(sb.Zones, ProviderInstance.Zones)
   375  	}
   376  	sb.Spaces = []networkingcommon.BackingSpace{}
   377  	if withSpaces {
   378  		// Note that full subnet data is generated from the SubnetIds in
   379  		// FakeSpace.Subnets().
   380  		sb.Spaces = []networkingcommon.BackingSpace{
   381  			&FakeSpace{
   382  				SpaceName: "default",
   383  				SubnetIds: []string{"192.168.0.0/24", "192.168.3.0/24"},
   384  				NextErr:   sb.NextErr},
   385  			&FakeSpace{
   386  				SpaceName: "dmz",
   387  				SubnetIds: []string{"192.168.1.0/24"},
   388  				NextErr:   sb.NextErr},
   389  			&FakeSpace{
   390  				SpaceName: "private",
   391  				SubnetIds: []string{"192.168.2.0/24"},
   392  				NextErr:   sb.NextErr},
   393  			&FakeSpace{
   394  				SpaceName: "private",
   395  				SubnetIds: []string{"192.168.2.0/24"},
   396  				NextErr:   sb.NextErr}, // duplicates are ignored when caching spaces.
   397  		}
   398  	}
   399  	sb.Subnets = []networkingcommon.BackingSubnet{}
   400  	if withSubnets {
   401  		info0 := networkingcommon.BackingSubnetInfo{
   402  			CIDR:              ProviderInstance.Subnets[0].CIDR,
   403  			ProviderId:        ProviderInstance.Subnets[0].ProviderId,
   404  			AllocatableIPLow:  ProviderInstance.Subnets[0].AllocatableIPLow.String(),
   405  			AllocatableIPHigh: ProviderInstance.Subnets[0].AllocatableIPHigh.String(),
   406  			AvailabilityZones: ProviderInstance.Subnets[0].AvailabilityZones,
   407  			SpaceName:         "private",
   408  		}
   409  		info1 := networkingcommon.BackingSubnetInfo{
   410  			CIDR:              ProviderInstance.Subnets[1].CIDR,
   411  			ProviderId:        ProviderInstance.Subnets[1].ProviderId,
   412  			AvailabilityZones: ProviderInstance.Subnets[1].AvailabilityZones,
   413  			SpaceName:         "dmz",
   414  		}
   415  
   416  		sb.Subnets = []networkingcommon.BackingSubnet{
   417  			&FakeSubnet{info0},
   418  			&FakeSubnet{info1},
   419  		}
   420  	}
   421  }
   422  
   423  func (sb *StubBacking) ModelConfig() (*config.Config, error) {
   424  	sb.MethodCall(sb, "ModelConfig")
   425  	if err := sb.NextErr(); err != nil {
   426  		return nil, err
   427  	}
   428  	return sb.EnvConfig, nil
   429  }
   430  
   431  func (sb *StubBacking) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   432  	sb.MethodCall(sb, "AvailabilityZones")
   433  	if err := sb.NextErr(); err != nil {
   434  		return nil, err
   435  	}
   436  	return sb.Zones, nil
   437  }
   438  
   439  func (sb *StubBacking) SetAvailabilityZones(zones []providercommon.AvailabilityZone) error {
   440  	sb.MethodCall(sb, "SetAvailabilityZones", zones)
   441  	return sb.NextErr()
   442  }
   443  
   444  func (sb *StubBacking) AllSpaces() ([]networkingcommon.BackingSpace, error) {
   445  	sb.MethodCall(sb, "AllSpaces")
   446  	if err := sb.NextErr(); err != nil {
   447  		return nil, err
   448  	}
   449  
   450  	// Filter duplicates.
   451  	seen := set.Strings{}
   452  	output := []networkingcommon.BackingSpace{}
   453  	for _, space := range sb.Spaces {
   454  		if seen.Contains(space.Name()) {
   455  			continue
   456  		}
   457  		seen.Add(space.Name())
   458  		output = append(output, space)
   459  	}
   460  	return output, nil
   461  }
   462  
   463  func (sb *StubBacking) AllSubnets() ([]networkingcommon.BackingSubnet, error) {
   464  	sb.MethodCall(sb, "AllSubnets")
   465  	if err := sb.NextErr(); err != nil {
   466  		return nil, err
   467  	}
   468  
   469  	// Filter duplicates.
   470  	seen := set.Strings{}
   471  	output := []networkingcommon.BackingSubnet{}
   472  	for _, subnet := range sb.Subnets {
   473  		if seen.Contains(subnet.CIDR()) {
   474  			continue
   475  		}
   476  		seen.Add(subnet.CIDR())
   477  		output = append(output, subnet)
   478  	}
   479  	return output, nil
   480  }
   481  
   482  func (sb *StubBacking) AddSubnet(subnetInfo networkingcommon.BackingSubnetInfo) (networkingcommon.BackingSubnet, error) {
   483  	sb.MethodCall(sb, "AddSubnet", subnetInfo)
   484  	if err := sb.NextErr(); err != nil {
   485  		return nil, err
   486  	}
   487  	fs := &FakeSubnet{info: subnetInfo}
   488  	sb.Subnets = append(sb.Subnets, fs)
   489  	return fs, nil
   490  }
   491  
   492  func (sb *StubBacking) AddSpace(name string, providerId network.Id, subnets []string, public bool) error {
   493  	sb.MethodCall(sb, "AddSpace", name, providerId, subnets, public)
   494  	if err := sb.NextErr(); err != nil {
   495  		return err
   496  	}
   497  	fs := &FakeSpace{SpaceName: name, SubnetIds: subnets, Public: public}
   498  	sb.Spaces = append(sb.Spaces, fs)
   499  	return nil
   500  }
   501  
   502  // GoString implements fmt.GoStringer.
   503  func (se *StubBacking) GoString() string {
   504  	return "&StubBacking{}"
   505  }
   506  
   507  // StubProvider implements a subset of environs.EnvironProvider
   508  // methods used in tests.
   509  type StubProvider struct {
   510  	*testing.Stub
   511  
   512  	Zones   []providercommon.AvailabilityZone
   513  	Subnets []network.SubnetInfo
   514  
   515  	environs.EnvironProvider // panic on any not implemented method call.
   516  }
   517  
   518  var _ environs.EnvironProvider = (*StubProvider)(nil)
   519  
   520  func (sp *StubProvider) Open(cfg *config.Config) (environs.Environ, error) {
   521  	sp.MethodCall(sp, "Open", cfg)
   522  	if err := sp.NextErr(); err != nil {
   523  		return nil, err
   524  	}
   525  	switch cfg.Name() {
   526  	case StubEnvironName:
   527  		return EnvironInstance, nil
   528  	case StubZonedEnvironName:
   529  		return ZonedEnvironInstance, nil
   530  	case StubNetworkingEnvironName:
   531  		return NetworkingEnvironInstance, nil
   532  	case StubZonedNetworkingEnvironName:
   533  		return ZonedNetworkingEnvironInstance, nil
   534  	}
   535  	panic("unexpected model name: " + cfg.Name())
   536  }
   537  
   538  // GoString implements fmt.GoStringer.
   539  func (se *StubProvider) GoString() string {
   540  	return "&StubProvider{}"
   541  }
   542  
   543  // StubEnviron is used in tests where environs.Environ is needed.
   544  type StubEnviron struct {
   545  	*testing.Stub
   546  
   547  	environs.Environ // panic on any not implemented method call
   548  }
   549  
   550  var _ environs.Environ = (*StubEnviron)(nil)
   551  
   552  // GoString implements fmt.GoStringer.
   553  func (se *StubEnviron) GoString() string {
   554  	return "&StubEnviron{}"
   555  }
   556  
   557  // StubZonedEnviron is used in tests where providercommon.ZonedEnviron
   558  // is needed.
   559  type StubZonedEnviron struct {
   560  	*testing.Stub
   561  
   562  	providercommon.ZonedEnviron // panic on any not implemented method call
   563  }
   564  
   565  var _ providercommon.ZonedEnviron = (*StubZonedEnviron)(nil)
   566  
   567  func (se *StubZonedEnviron) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   568  	se.MethodCall(se, "AvailabilityZones")
   569  	if err := se.NextErr(); err != nil {
   570  		return nil, err
   571  	}
   572  	return ProviderInstance.Zones, nil
   573  }
   574  
   575  // GoString implements fmt.GoStringer.
   576  func (se *StubZonedEnviron) GoString() string {
   577  	return "&StubZonedEnviron{}"
   578  }
   579  
   580  // StubNetworkingEnviron is used in tests where
   581  // environs.NetworkingEnviron is needed.
   582  type StubNetworkingEnviron struct {
   583  	*testing.Stub
   584  
   585  	environs.NetworkingEnviron // panic on any not implemented method call
   586  }
   587  
   588  var _ environs.NetworkingEnviron = (*StubNetworkingEnviron)(nil)
   589  
   590  func (se *StubNetworkingEnviron) Subnets(instId instance.Id, subIds []network.Id) ([]network.SubnetInfo, error) {
   591  	se.MethodCall(se, "Subnets", instId, subIds)
   592  	if err := se.NextErr(); err != nil {
   593  		return nil, err
   594  	}
   595  	return ProviderInstance.Subnets, nil
   596  }
   597  
   598  func (se *StubNetworkingEnviron) SupportsSpaces() (bool, error) {
   599  	se.MethodCall(se, "SupportsSpaces")
   600  	if err := se.NextErr(); err != nil {
   601  		return false, err
   602  	}
   603  	return true, nil
   604  }
   605  
   606  // GoString implements fmt.GoStringer.
   607  func (se *StubNetworkingEnviron) GoString() string {
   608  	return "&StubNetworkingEnviron{}"
   609  }
   610  
   611  // StubZonedNetworkingEnviron is used in tests where features from
   612  // both environs.Networking and providercommon.ZonedEnviron are
   613  // needed.
   614  type StubZonedNetworkingEnviron struct {
   615  	*testing.Stub
   616  
   617  	// panic on any not implemented method call
   618  	providercommon.ZonedEnviron
   619  	environs.Networking
   620  }
   621  
   622  // GoString implements fmt.GoStringer.
   623  func (se *StubZonedNetworkingEnviron) GoString() string {
   624  	return "&StubZonedNetworkingEnviron{}"
   625  }
   626  
   627  func (se *StubZonedNetworkingEnviron) SupportsSpaces() (bool, error) {
   628  	se.MethodCall(se, "SupportsSpaces")
   629  	if err := se.NextErr(); err != nil {
   630  		return false, err
   631  	}
   632  	return true, nil
   633  }
   634  
   635  func (se *StubZonedNetworkingEnviron) Subnets(instId instance.Id, subIds []network.Id) ([]network.SubnetInfo, error) {
   636  	se.MethodCall(se, "Subnets", instId, subIds)
   637  	if err := se.NextErr(); err != nil {
   638  		return nil, err
   639  	}
   640  	return ProviderInstance.Subnets, nil
   641  }
   642  
   643  func (se *StubZonedNetworkingEnviron) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   644  	se.MethodCall(se, "AvailabilityZones")
   645  	if err := se.NextErr(); err != nil {
   646  		return nil, err
   647  	}
   648  	return ProviderInstance.Zones, nil
   649  }