github.com/coreos/mantle@v0.13.0/platform/local/flight.go (about)

     1  // Copyright 2015 CoreOS, Inc.
     2  // Copyright 2018 Red Hat
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package local
    17  
    18  import (
    19  	"fmt"
    20  	"sync/atomic"
    21  
    22  	"github.com/coreos/go-omaha/omaha"
    23  	"github.com/vishvananda/netns"
    24  
    25  	"github.com/coreos/mantle/lang/destructor"
    26  	"github.com/coreos/mantle/network"
    27  	"github.com/coreos/mantle/network/ntp"
    28  	"github.com/coreos/mantle/platform"
    29  	"github.com/coreos/mantle/system/ns"
    30  )
    31  
    32  const (
    33  	listenPortBase = 30000
    34  )
    35  
    36  type LocalFlight struct {
    37  	destructor.MultiDestructor
    38  	*platform.BaseFlight
    39  	Dnsmasq    *Dnsmasq
    40  	SimpleEtcd *SimpleEtcd
    41  	NTPServer  *ntp.Server
    42  	nshandle   netns.NsHandle
    43  	listenPort int32
    44  }
    45  
    46  func NewLocalFlight(opts *platform.Options, platformName platform.Name) (*LocalFlight, error) {
    47  	nshandle, err := ns.Create()
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	nsdialer := network.NewNsDialer(nshandle)
    53  	bf, err := platform.NewBaseFlightWithDialer(opts, platformName, "", nsdialer)
    54  	if err != nil {
    55  		nshandle.Close()
    56  		return nil, err
    57  	}
    58  
    59  	lf := &LocalFlight{
    60  		BaseFlight: bf,
    61  		nshandle:   nshandle,
    62  		listenPort: listenPortBase,
    63  	}
    64  	lf.AddDestructor(lf.BaseFlight)
    65  	lf.AddCloser(&lf.nshandle)
    66  
    67  	// dnsmasq and etcd must be launched in the new namespace
    68  	nsExit, err := ns.Enter(lf.nshandle)
    69  	if err != nil {
    70  		lf.Destroy()
    71  		return nil, err
    72  	}
    73  	defer nsExit()
    74  
    75  	lf.Dnsmasq, err = NewDnsmasq()
    76  	if err != nil {
    77  		lf.Destroy()
    78  		return nil, err
    79  	}
    80  	lf.AddDestructor(lf.Dnsmasq)
    81  
    82  	lf.SimpleEtcd, err = NewSimpleEtcd()
    83  	if err != nil {
    84  		lf.Destroy()
    85  		return nil, err
    86  	}
    87  	lf.AddDestructor(lf.SimpleEtcd)
    88  
    89  	lf.NTPServer, err = ntp.NewServer(":123")
    90  	if err != nil {
    91  		lf.Destroy()
    92  		return nil, err
    93  	}
    94  	lf.AddCloser(lf.NTPServer)
    95  	go lf.NTPServer.Serve()
    96  
    97  	return lf, nil
    98  }
    99  
   100  func (lf *LocalFlight) NewCluster(rconf *platform.RuntimeConfig) (*LocalCluster, error) {
   101  	lc := &LocalCluster{
   102  		flight: lf,
   103  	}
   104  
   105  	var err error
   106  	lc.BaseCluster, err = platform.NewBaseCluster(lf.BaseFlight, rconf)
   107  	if err != nil {
   108  		lc.Destroy()
   109  		return nil, err
   110  	}
   111  	lc.AddDestructor(lc.BaseCluster)
   112  
   113  	// Omaha server must be launched in the new namespace
   114  	nsExit, err := ns.Enter(lf.nshandle)
   115  	if err != nil {
   116  		lc.Destroy()
   117  		return nil, err
   118  	}
   119  	defer nsExit()
   120  
   121  	omahaServer, err := omaha.NewTrivialServer(fmt.Sprintf(":%d", lf.newListenPort()))
   122  	if err != nil {
   123  		lc.Destroy()
   124  		return nil, err
   125  	}
   126  	lc.OmahaServer = OmahaWrapper{TrivialServer: omahaServer}
   127  	lc.AddDestructor(lc.OmahaServer)
   128  	go lc.OmahaServer.Serve()
   129  
   130  	// does not lf.AddCluster() since we are not the top-level object
   131  
   132  	return lc, nil
   133  }
   134  
   135  func (lf *LocalFlight) newListenPort() int {
   136  	return int(atomic.AddInt32(&lf.listenPort, 1))
   137  }
   138  
   139  func (lf *LocalFlight) Destroy() {
   140  	lf.MultiDestructor.Destroy()
   141  }