Пример #1
0
func (s *BootstrapSuite) testToolsMetadata(c *gc.C, exploded bool) {
	envtesting.RemoveFakeToolsMetadata(c, s.toolsStorage)

	_, cmd, err := s.initBootstrapCommand(c, nil,
		"--model-config", s.b64yamlControllerModelConfig,
		"--hosted-model-config", s.b64yamlHostedModelConfig,
		"--instance-id", string(s.instanceId),
	)
	c.Assert(err, jc.ErrorIsNil)
	err = cmd.Run(nil)
	c.Assert(err, jc.ErrorIsNil)

	// We don't write metadata at bootstrap anymore.
	simplestreamsMetadata, err := envtools.ReadMetadata(s.toolsStorage, "released")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(simplestreamsMetadata, gc.HasLen, 0)

	// The tools should have been added to tools storage, and
	// exploded into each of the supported series of
	// the same operating system if the tools were uploaded.
	st, err := state.Open(testing.ModelTag, &mongo.MongoInfo{
		Info: mongo.Info{
			Addrs:  []string{gitjujutesting.MgoServer.Addr()},
			CACert: testing.CACert,
		},
		Password: testPassword,
	}, mongotest.DialOpts(), environs.NewStatePolicy())
	c.Assert(err, jc.ErrorIsNil)
	defer st.Close()
	expectedSeries := make(set.Strings)
	if exploded {
		for _, ser := range series.SupportedSeries() {
			os, err := series.GetOSFromSeries(ser)
			c.Assert(err, jc.ErrorIsNil)
			hostos, err := series.GetOSFromSeries(series.HostSeries())
			c.Assert(err, jc.ErrorIsNil)
			if os == hostos {
				expectedSeries.Add(ser)
			}
		}
	} else {
		expectedSeries.Add(series.HostSeries())
	}

	storage, err := st.ToolsStorage()
	c.Assert(err, jc.ErrorIsNil)
	defer storage.Close()
	metadata, err := storage.AllMetadata()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(metadata, gc.HasLen, expectedSeries.Size())
	for _, m := range metadata {
		v := version.MustParseBinary(m.Version)
		c.Assert(expectedSeries.Contains(v.Series), jc.IsTrue)
	}
}
Пример #2
0
func (s *syslogSuite) SetUpTest(c *gc.C) {
	if runtime.GOOS != "linux" {
		c.Skip(fmt.Sprintf("this test requires a controller, therefore does not support %q", runtime.GOOS))
	}
	currentSeries := series.HostSeries()
	osFromSeries, err := series.GetOSFromSeries(currentSeries)
	c.Assert(err, jc.ErrorIsNil)
	if osFromSeries != os.Ubuntu {
		c.Skip(fmt.Sprintf("this test requires a controller, therefore does not support OS %q only Ubuntu", osFromSeries.String()))
	}
	s.AgentSuite.SetUpTest(c)
	// TODO(perrito666) 200160701:
	// This needs to be done to stop the test from trying to install mongo
	// while running, but it is a huge footprint for such little benefit.
	// This test should not need JujuConnSuite or AgentSuite.
	s.fakeEnsureMongo = agenttest.InstallFakeEnsureMongo(s)

	done := make(chan struct{})
	s.received = make(chan rfc5424test.Message)
	addr := s.createSyslogServer(c, s.received, done)

	// Leave log forwarding disabled initially, it will be enabled
	// via a model config update in the test.
	err = s.State.UpdateModelConfig(map[string]interface{}{
		"syslog-host":        addr,
		"syslog-ca-cert":     coretesting.CACert,
		"syslog-client-cert": coretesting.ServerCert,
		"syslog-client-key":  coretesting.ServerKey,
	}, nil, nil)
	c.Assert(err, jc.ErrorIsNil)

	s.logsCh, err = logsender.InstallBufferedLogWriter(1000)
	c.Assert(err, jc.ErrorIsNil)
}
Пример #3
0
func versionInitSystem(ser string) (string, error) {
	seriesos, err := series.GetOSFromSeries(ser)
	if err != nil {
		notFound := errors.NotFoundf("init system for series %q", ser)
		return "", errors.Wrap(err, notFound)
	}

	switch seriesos {
	case os.Windows:
		return InitSystemWindows, nil
	case os.Ubuntu:
		switch ser {
		case "precise", "quantal", "raring", "saucy", "trusty", "utopic":
			return InitSystemUpstart, nil
		default:
			// vivid and later
			if featureflag.Enabled(feature.LegacyUpstart) {
				return InitSystemUpstart, nil
			}
			return InitSystemSystemd, nil
		}
	case os.CentOS:
		return InitSystemSystemd, nil
	}
	return "", errors.NotFoundf("unknown os %q (from series %q), init system", seriesos, ser)
}
Пример #4
0
Файл: tools.go Проект: bac/juju
// validateUploadAllowed returns an error if an attempt to upload tools should
// not be allowed.
func validateUploadAllowed(env environs.Environ, toolsArch, toolsSeries *string, validator constraints.Validator) error {
	// Now check that the architecture and series for which we are setting up an
	// environment matches that from which we are bootstrapping.
	hostArch := arch.HostArch()
	// We can't build tools for a different architecture if one is specified.
	if toolsArch != nil && *toolsArch != hostArch {
		return fmt.Errorf("cannot use agent built for %q using a machine running on %q", *toolsArch, hostArch)
	}
	hostOS := jujuos.HostOS()
	if toolsSeries != nil {
		toolsSeriesOS, err := series.GetOSFromSeries(*toolsSeries)
		if err != nil {
			return errors.Trace(err)
		}
		if !toolsSeriesOS.EquivalentTo(hostOS) {
			return errors.Errorf("cannot use agent built for %q using a machine running %q", *toolsSeries, hostOS)
		}
	}
	// If no architecture is specified, ensure the target provider supports instances matching our architecture.
	if _, err := validator.Validate(constraints.Value{Arch: &hostArch}); err != nil {
		return errors.Errorf(
			"model %q of type %s does not support instances running on %q",
			env.Config().Name(), env.Config().Type(), hostArch,
		)
	}
	return nil
}
Пример #5
0
// newRole creates a gwacl.Role object (an Azure Virtual Machine) which uses
// the given Virtual Hard Drive.
//
// roleSize is the name of one of Azure's machine types, e.g. ExtraSmall,
// Large, A6 etc.
func (env *azureEnviron) newRole(roleSize string, vhd *gwacl.OSVirtualHardDisk, stateServer bool, userdata, ser string, snapshot *azureEnviron) (*gwacl.Role, error) {
	// Do some common initialization
	roleName := gwacl.MakeRandomRoleName("juju")
	hostname := roleName
	password := gwacl.MakeRandomPassword()

	os, err := series.GetOSFromSeries(ser)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// Generate a Network Configuration with the initially required ports open.
	networkConfigurationSet := gwacl.NewNetworkConfigurationSet(env.getInitialEndpoints(stateServer), nil)

	var role *gwacl.Role
	switch os {
	case jujuos.Windows:
		role, err = makeWindowsRole(password, roleSize, roleName, userdata, vhd, networkConfigurationSet, snapshot)
	default:
		role, err = makeLinuxRole(hostname, password, roleSize, roleName, userdata, vhd, networkConfigurationSet)
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	role.AvailabilitySetName = "juju"
	return role, nil
}
Пример #6
0
// UserdataConfig is supposed to take in an instanceConfig as well as a
// cloudinit.cloudConfig and add attributes in the cloudinit structure based on
// the values inside instanceConfig and on the series
func NewUserdataConfig(icfg *instancecfg.InstanceConfig, conf cloudinit.CloudConfig) (UserdataConfig, error) {
	// TODO(ericsnow) bug #1426217
	// Protect icfg and conf better.
	operatingSystem, err := series.GetOSFromSeries(icfg.Series)
	if err != nil {
		return nil, err
	}

	base := baseConfigure{
		tag:  names.NewMachineTag(icfg.MachineId),
		icfg: icfg,
		conf: conf,
		os:   operatingSystem,
	}

	switch operatingSystem {
	case os.Ubuntu:
		return &unixConfigure{base}, nil
	case os.CentOS:
		return &unixConfigure{base}, nil
	case os.Windows:
		return &windowsConfigure{base}, nil
	default:
		return nil, errors.NotSupportedf("OS %s", icfg.Series)
	}
}
Пример #7
0
func (*CurrentSuite) TestCurrentSeries(c *gc.C) {
	s := series.HostSeries()
	if s == "unknown" {
		s = "n/a"
	}
	out, err := exec.Command("lsb_release", "-c").CombinedOutput()

	if err != nil {
		// If the command fails (for instance if we're running on some other
		// platform) then CurrentSeries should be unknown.
		switch runtime.GOOS {
		case "darwin":
			c.Check(s, gc.Matches, `mavericks|mountainlion|lion|snowleopard`)
		case "windows":
			c.Check(s, gc.Matches, `win2012hvr2|win2012hv|win2012|win2012r2|win8|win81|win7`)
		default:
			current_os, err := series.GetOSFromSeries(s)
			c.Assert(err, gc.IsNil)
			if s != "n/a" {
				// There is no lsb_release command on CentOS.
				if current_os == os.CentOS {
					c.Check(s, gc.Matches, `centos7`)
				}
			}
		}
	} else {
		c.Assert(string(out), gc.Equals, "Codename:\t"+s+"\n")
	}
}
Пример #8
0
// getDisks builds the raw spec for the disks that should be attached to
// the new instances and returns it. This will always include a root
// disk with characteristics determined by the provides args and
// constraints.
func getDisks(spec *instances.InstanceSpec, cons constraints.Value, ser, eUUID string) ([]google.DiskSpec, error) {
	size := common.MinRootDiskSizeGiB(ser)
	if cons.RootDisk != nil && *cons.RootDisk > size {
		size = common.MiBToGiB(*cons.RootDisk)
	}
	var imageURL string
	os, err := series.GetOSFromSeries(ser)
	if err != nil {
		return nil, errors.Trace(err)
	}
	switch os {
	case jujuos.Ubuntu:
		imageURL = ubuntuImageBasePath
	case jujuos.Windows:
		imageURL = windowsImageBasePath
	default:
		return nil, errors.Errorf("os %s is not supported on the gce provider", os.String())
	}
	dSpec := google.DiskSpec{
		Series:      ser,
		SizeHintGB:  size,
		ImageURL:    imageURL + spec.Image.Id,
		Boot:        true,
		AutoDelete:  true,
		Description: eUUID,
	}
	if cons.RootDisk != nil && dSpec.TooSmall() {
		msg := "Ignoring root-disk constraint of %dM because it is smaller than the GCE image size of %dG"
		logger.Infof(msg, *cons.RootDisk, google.MinDiskSizeGB(ser))
	}
	return []google.DiskSpec{dSpec}, nil
}
func getContainerInstance() (cont []ContainerInstance, err error) {
	current_os, err := series.GetOSFromSeries(series.HostSeries())
	if err != nil {
		return nil, err
	}

	switch current_os {
	case jujuos.CentOS:
		cont = []ContainerInstance{
			{instance.LXC, [][]string{
				{"lxc"},
				{"cloud-image-utils"},
			}},
			{instance.KVM, [][]string{
				{"uvtool-libvirt"},
				{"uvtool"},
			}},
		}
	default:
		cont = []ContainerInstance{
			{instance.LXC, [][]string{
				{"--target-release", "precise-updates/cloud-tools", "lxc"},
				{"--target-release", "precise-updates/cloud-tools", "cloud-image-utils"},
			}},
			{instance.KVM, [][]string{
				{"uvtool-libvirt"},
				{"uvtool"},
			}},
		}
	}

	return cont, nil
}
Пример #10
0
func (s *environBrokerSuite) TestGetDisks(c *gc.C) {
	for _, test := range getDisksTests {
		diskSpecs, err := gce.GetDisks(s.spec, s.StartInstArgs.Constraints, test.Series, "32f7d570-5bac-4b72-b169-250c24a94b2b", false)
		if test.error != nil {
			c.Assert(err, gc.Equals, err)
		} else {
			c.Assert(err, jc.ErrorIsNil)
			c.Assert(diskSpecs, gc.HasLen, 1)

			diskSpec := diskSpecs[0]

			os, err := series.GetOSFromSeries(test.Series)
			c.Assert(err, jc.ErrorIsNil)
			switch os {
			case jujuos.Ubuntu:
				c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(8))
			case jujuos.Windows:
				c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(40))
			default:
				c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(8))
			}
			c.Check(diskSpec.ImageURL, gc.Equals, test.basePath+s.spec.Image.Id)
		}
	}

	diskSpecs, err := gce.GetDisks(s.spec, s.StartInstArgs.Constraints, "trusty", "32f7d570-5bac-4b72-b169-250c24a94b2b", true)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(diskSpecs, gc.HasLen, 1)
	spec := diskSpecs[0]
	c.Assert(spec.ImageURL, gc.Equals, gce.UbuntuDailyImageBasePath+s.spec.Image.Id)
}
Пример #11
0
// ComposeUserData fills out the provided cloudinit configuration structure
// so it is suitable for initialising a machine with the given configuration,
// and then renders it and encodes it using the supplied renderer.
// When calling ComposeUserData a encoding implementation must be chosen from
// the providerinit/encoders package according to the need of the provider.
//
// If the provided cloudcfg is nil, a new one will be created internally.
func ComposeUserData(icfg *instancecfg.InstanceConfig, cloudcfg cloudinit.CloudConfig, renderer renderers.ProviderRenderer) ([]byte, error) {
	if cloudcfg == nil {
		var err error
		cloudcfg, err = cloudinit.New(icfg.Series)
		if err != nil {
			return nil, errors.Trace(err)
		}
	}
	_, err := configureCloudinit(icfg, cloudcfg)
	if err != nil {
		return nil, errors.Trace(err)
	}
	operatingSystem, err := series.GetOSFromSeries(icfg.Series)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// This might get replaced by a renderer.RenderUserdata which will either
	// render it as YAML or Bash since some CentOS images might ship without cloudnit
	udata, err := cloudcfg.RenderYAML()
	if err != nil {
		return nil, errors.Trace(err)
	}
	udata, err = renderer.EncodeUserdata(udata, operatingSystem)
	if err != nil {
		return nil, errors.Trace(err)
	}
	logger.Tracef("Generated cloud init:\n%s", string(udata))
	return udata, err
}
Пример #12
0
// populateTools stores uploaded tools in provider storage
// and updates the tools metadata.
func (c *BootstrapCommand) populateTools(st *state.State, env environs.Environ) error {
	agentConfig := c.CurrentConfig()
	dataDir := agentConfig.DataDir()

	current := version.Binary{
		Number: jujuversion.Current,
		Arch:   arch.HostArch(),
		Series: series.HostSeries(),
	}
	tools, err := agenttools.ReadTools(dataDir, current)
	if err != nil {
		return errors.Trace(err)
	}

	data, err := ioutil.ReadFile(filepath.Join(
		agenttools.SharedToolsDir(dataDir, current),
		"tools.tar.gz",
	))
	if err != nil {
		return errors.Trace(err)
	}

	toolstorage, err := st.ToolsStorage()
	if err != nil {
		return errors.Trace(err)
	}
	defer toolstorage.Close()

	var toolsVersions []version.Binary
	if strings.HasPrefix(tools.URL, "file://") {
		// Tools were uploaded: clone for each series of the same OS.
		os, err := series.GetOSFromSeries(tools.Version.Series)
		if err != nil {
			return errors.Trace(err)
		}
		osSeries := series.OSSupportedSeries(os)
		for _, series := range osSeries {
			toolsVersion := tools.Version
			toolsVersion.Series = series
			toolsVersions = append(toolsVersions, toolsVersion)
		}
	} else {
		// Tools were downloaded from an external source: don't clone.
		toolsVersions = []version.Binary{tools.Version}
	}

	for _, toolsVersion := range toolsVersions {
		metadata := binarystorage.Metadata{
			Version: toolsVersion.String(),
			Size:    tools.Size,
			SHA256:  tools.SHA256,
		}
		logger.Debugf("Adding tools: %v", toolsVersion)
		if err := toolstorage.Add(bytes.NewReader(data), metadata); err != nil {
			return errors.Trace(err)
		}
	}
	return nil
}
Пример #13
0
Файл: main.go Проект: bac/juju
func shouldWarnJuju1x() bool {
	// this code only applies to Ubuntu, where we renamed Juju 1.x to juju-1.
	ostype, err := series.GetOSFromSeries(series.HostSeries())
	if err != nil || ostype != utilsos.Ubuntu {
		return false
	}
	return osenv.Juju1xEnvConfigExists() && !juju2xConfigDataExists()
}
Пример #14
0
func (w *unixConfigure) setDataDirPermissions() string {
	seriesos, _ := series.GetOSFromSeries(w.icfg.Series)
	var user string
	switch seriesos {
	case os.CentOS:
		user = "******"
	default:
		user = "******"
	}
	return fmt.Sprintf("chown %s:adm %s", user, w.icfg.LogDir)
}
Пример #15
0
func (s *supportedSeriesSuite) TestGetOSFromSeries(c *gc.C) {
	for _, t := range getOSFromSeriesTests {
		got, err := series.GetOSFromSeries(t.series)
		if t.err != "" {
			c.Assert(err, gc.ErrorMatches, t.err)
		} else {
			c.Check(err, jc.ErrorIsNil)
			c.Assert(got, gc.Equals, t.want)
		}
	}
}
Пример #16
0
// osVal will lookup the value of the key valname
// in the apropriate map, based on the series. This will
// help reduce boilerplate code
func osVal(ser string, valname osVarType) (string, error) {
	os, err := series.GetOSFromSeries(ser)
	if err != nil {
		return "", err
	}
	switch os {
	case jujuos.Windows:
		return winVals[valname], nil
	default:
		return nixVals[valname], nil
	}
}
Пример #17
0
// SeriesImage gets an instances.Image for the specified series, image stream
// and location. The resulting Image's ID is in the URN format expected by
// Azure Resource Manager.
//
// For Ubuntu, we query the SKUs to determine the most recent point release
// for a series.
func SeriesImage(
	series, stream, location string,
	client compute.VirtualMachineImagesClient,
) (*instances.Image, error) {
	seriesOS, err := jujuseries.GetOSFromSeries(series)
	if err != nil {
		return nil, errors.Trace(err)
	}

	var publisher, offering, sku string
	switch seriesOS {
	case os.Ubuntu:
		publisher = ubuntuPublisher
		offering = ubuntuOffering
		sku, err = ubuntuSKU(series, stream, location, client)
		if err != nil {
			return nil, errors.Annotatef(err, "selecting SKU for %s", series)
		}

	case os.Windows:
		publisher = windowsPublisher
		offering = windowsOffering
		switch series {
		case "win2012":
			sku = "2012-Datacenter"
		case "win2012r2":
			sku = "2012-R2-Datacenter"
		default:
			return nil, errors.NotSupportedf("deploying %s", series)
		}

	case os.CentOS:
		publisher = centOSPublisher
		offering = centOSOffering
		switch series {
		case "centos7":
			sku = "7.1"
		default:
			return nil, errors.NotSupportedf("deploying %s", series)
		}

	default:
		// TODO(axw) CentOS
		return nil, errors.NotSupportedf("deploying %s", seriesOS)
	}

	return &instances.Image{
		Id:       fmt.Sprintf("%s:%s:%s:latest", publisher, offering, sku),
		Arch:     arch.AMD64,
		VirtType: "Hyper-V",
	}, nil
}
Пример #18
0
func (w *proxyWorker) writeEnvironment() error {
	// TODO(dfc) this should be replaced with a switch on os.HostOS()
	osystem, err := series.GetOSFromSeries(series.HostSeries())
	if err != nil {
		return err
	}
	switch osystem {
	case os.Windows:
		return w.writeEnvironmentToRegistry()
	default:
		return w.writeEnvironmentFile()
	}
}
Пример #19
0
func (sf *statusFormatter) formatApplication(name string, application params.ApplicationStatus) applicationStatus {
	appOS, _ := series.GetOSFromSeries(application.Series)
	var (
		charmOrigin = ""
		charmName   = ""
		charmRev    = 0
	)
	if curl, err := charm.ParseURL(application.Charm); err != nil {
		// We should never fail to parse a charm url sent back
		// but if we do, don't crash.
		logger.Errorf("failed to parse charm: %v", err)
	} else {
		switch curl.Schema {
		case "cs":
			charmOrigin = "jujucharms"
		case "local":
			charmOrigin = "local"
		default:
			charmOrigin = "unknown"
		}
		charmName = curl.Name
		charmRev = curl.Revision
	}

	out := applicationStatus{
		Err:           application.Err,
		Charm:         application.Charm,
		Series:        application.Series,
		OS:            strings.ToLower(appOS.String()),
		CharmOrigin:   charmOrigin,
		CharmName:     charmName,
		CharmRev:      charmRev,
		Exposed:       application.Exposed,
		Life:          application.Life,
		Relations:     application.Relations,
		CanUpgradeTo:  application.CanUpgradeTo,
		SubordinateTo: application.SubordinateTo,
		Units:         make(map[string]unitStatus),
		StatusInfo:    sf.getServiceStatusInfo(application),
		Version:       application.WorkloadVersion,
	}
	for k, m := range application.Units {
		out.Units[k] = sf.formatUnit(unitFormatInfo{
			unit:            m,
			unitName:        k,
			applicationName: name,
			meterStatuses:   application.MeterStatuses,
		})
	}
	return out
}
Пример #20
0
func newOSProfile(
	vmName string,
	instanceConfig *instancecfg.InstanceConfig,
	randomAdminPassword func() string,
) (*compute.OSProfile, os.OSType, error) {
	logger.Debugf("creating OS profile for %q", vmName)

	customData, err := providerinit.ComposeUserData(instanceConfig, nil, AzureRenderer{})
	if err != nil {
		return nil, os.Unknown, errors.Annotate(err, "composing user data")
	}

	osProfile := &compute.OSProfile{
		ComputerName: to.StringPtr(vmName),
		CustomData:   to.StringPtr(string(customData)),
	}

	seriesOS, err := jujuseries.GetOSFromSeries(instanceConfig.Series)
	if err != nil {
		return nil, os.Unknown, errors.Trace(err)
	}
	switch seriesOS {
	case os.Ubuntu, os.CentOS:
		// SSH keys are handled by custom data, but must also be
		// specified in order to forego providing a password, and
		// disable password authentication.
		publicKeys := []compute.SSHPublicKey{{
			Path:    to.StringPtr("/home/ubuntu/.ssh/authorized_keys"),
			KeyData: to.StringPtr(instanceConfig.AuthorizedKeys),
		}}
		osProfile.AdminUsername = to.StringPtr("ubuntu")
		osProfile.LinuxConfiguration = &compute.LinuxConfiguration{
			DisablePasswordAuthentication: to.BoolPtr(true),
			SSH: &compute.SSHConfiguration{PublicKeys: &publicKeys},
		}
	case os.Windows:
		osProfile.AdminUsername = to.StringPtr("JujuAdministrator")
		// A password is required by Azure, but we will never use it.
		// We generate something sufficiently long and random that it
		// should be infeasible to guess.
		osProfile.AdminPassword = to.StringPtr(randomAdminPassword())
		osProfile.WindowsConfiguration = &compute.WindowsConfiguration{
			ProvisionVMAgent:       to.BoolPtr(true),
			EnableAutomaticUpdates: to.BoolPtr(true),
			// TODO(?) add WinRM configuration here.
		}
	default:
		return nil, os.Unknown, errors.NotSupportedf("%s", seriesOS)
	}
	return osProfile, seriesOS, nil
}
Пример #21
0
// newRawInstance is where the new physical instance is actually
// provisioned, relative to the provided args and spec. Info for that
// low-level instance is returned.
func (env *environ) newRawInstance(args environs.StartInstanceParams, spec *instances.InstanceSpec) (*google.Instance, error) {
	machineID := common.MachineFullName(env, args.InstanceConfig.MachineId)

	os, err := series.GetOSFromSeries(args.InstanceConfig.Series)
	if err != nil {
		return nil, errors.Trace(err)
	}

	metadata, err := getMetadata(args, os)
	if err != nil {
		return nil, errors.Trace(err)
	}
	tags := []string{
		env.globalFirewallName(),
		machineID,
	}

	cfg := env.Config()
	eUUID, ok := cfg.UUID()
	if !ok {
		return nil, errors.NotFoundf("UUID necessary to create the instance disk")
	}

	disks, err := getDisks(spec, args.Constraints, args.InstanceConfig.Series, eUUID)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// TODO(ericsnow) Use the env ID for the network name (instead of default)?
	// TODO(ericsnow) Make the network name configurable?
	// TODO(ericsnow) Support multiple networks?
	// TODO(ericsnow) Use a different net interface name? Configurable?
	instSpec := google.InstanceSpec{
		ID:                machineID,
		Type:              spec.InstanceType.Name,
		Disks:             disks,
		NetworkInterfaces: []string{"ExternalNAT"},
		Metadata:          metadata,
		Tags:              tags,
		// Network is omitted (left empty).
	}

	zones, err := env.parseAvailabilityZones(args)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst, err := env.gce.AddInstance(instSpec, zones...)
	return inst, errors.Trace(err)
}
Пример #22
0
// MinDiskSizeGB is the minimum/default size (in megabytes) for
// GCE disks.
//
// Note: GCE does not currently have an official minimum disk size.
// However, in testing we found the minimum size to be 10 GB for ubuntu
// and 50 GB for windows due to the image size. See gceapi message.
//
// gceapi: Requested disk size cannot be smaller than the image size (10 GB)
func MinDiskSizeGB(ser string) uint64 {
	// See comment below that explains why we're ignoring the error
	os, _ := series.GetOSFromSeries(ser)
	switch os {
	case jujuos.Ubuntu:
		return 10
	case jujuos.Windows:
		return 50
	// On default we just return a "sane" default since the error
	// will be propagated through the api and appear in juju status anyway
	default:
		return 10
	}
}
Пример #23
0
// MinRootDiskSizeGiB is the minimum size for the root disk of an
// instance, in Gigabytes. This value accommodates the anticipated
// size of the initial image, any updates, and future application
// data.
func MinRootDiskSizeGiB(ser string) uint64 {
	// See comment below that explains why we're ignoring the error
	os, _ := series.GetOSFromSeries(ser)
	switch os {
	case jujuos.Ubuntu, jujuos.CentOS:
		return 8
	case jujuos.Windows:
		return 40
	// By default we just return a "sane" default, since the error will just
	// be returned by the api and seen in juju status
	default:
		return 8
	}
}
Пример #24
0
// newRawInstance is where the new physical instance is actually
// provisioned, relative to the provided args and spec. Info for that
// low-level instance is returned.
func (env *environ) newRawInstance(args environs.StartInstanceParams, spec *instances.InstanceSpec) (*google.Instance, error) {
	hostname, err := env.namespace.Hostname(args.InstanceConfig.MachineId)
	if err != nil {
		return nil, errors.Trace(err)
	}

	os, err := series.GetOSFromSeries(args.InstanceConfig.Series)
	if err != nil {
		return nil, errors.Trace(err)
	}

	metadata, err := getMetadata(args, os)
	if err != nil {
		return nil, errors.Trace(err)
	}
	tags := []string{
		env.globalFirewallName(),
		hostname,
	}

	disks, err := getDisks(
		spec, args.Constraints, args.InstanceConfig.Series, env.Config().UUID(), env.Config().ImageStream() == "daily",
	)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// TODO(ericsnow) Use the env ID for the network name (instead of default)?
	// TODO(ericsnow) Make the network name configurable?
	// TODO(ericsnow) Support multiple networks?
	// TODO(ericsnow) Use a different net interface name? Configurable?
	instSpec := google.InstanceSpec{
		ID:                hostname,
		Type:              spec.InstanceType.Name,
		Disks:             disks,
		NetworkInterfaces: []string{"ExternalNAT"},
		Metadata:          metadata,
		Tags:              tags,
		// Network is omitted (left empty).
	}

	zones, err := env.parseAvailabilityZones(args)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst, err := env.gce.AddInstance(instSpec, zones...)
	return inst, errors.Trace(err)
}
Пример #25
0
// uploadTools compiles jujud from $GOPATH and uploads it into the supplied
// storage. If no version has been explicitly chosen, the version number
// reported by the built tools will be based on the client version number.
// In any case, the version number reported will have a build component higher
// than that of any otherwise-matching available envtools.
// uploadTools resets the chosen version and replaces the available tools
// with the ones just uploaded.
func (context *upgradeContext) uploadTools(buildAgent bool) (err error) {
	// TODO(fwereade): this is kinda crack: we should not assume that
	// jujuversion.Current matches whatever source happens to be built. The
	// ideal would be:
	//  1) compile jujud from $GOPATH into some build dir
	//  2) get actual version with `jujud version`
	//  3) check actual version for compatibility with CLI tools
	//  4) generate unique build version with reference to available tools
	//  5) force-version that unique version into the dir directly
	//  6) archive and upload the build dir
	// ...but there's no way we have time for that now. In the meantime,
	// considering the use cases, this should work well enough; but it
	// won't detect an incompatible major-version change, which is a shame.
	//
	// TODO(cherylj) If the determination of version changes, we will
	// need to also change the upgrade version checks in Run() that check
	// if a major upgrade is allowed.
	if context.chosen == version.Zero {
		context.chosen = context.client
	}
	context.chosen = uploadVersion(context.chosen, context.tools)

	builtTools, err := sync.BuildAgentTarball(buildAgent, &context.chosen, "upgrade")
	if err != nil {
		return errors.Trace(err)
	}
	defer os.RemoveAll(builtTools.Dir)

	uploadToolsVersion := builtTools.Version
	uploadToolsVersion.Number = context.chosen
	toolsPath := path.Join(builtTools.Dir, builtTools.StorageName)
	logger.Infof("uploading agent binary %v (%dkB) to Juju controller", uploadToolsVersion, (builtTools.Size+512)/1024)
	f, err := os.Open(toolsPath)
	if err != nil {
		return errors.Trace(err)
	}
	defer f.Close()
	os, err := series.GetOSFromSeries(builtTools.Version.Series)
	if err != nil {
		return errors.Trace(err)
	}
	additionalSeries := series.OSSupportedSeries(os)
	uploaded, err := context.apiClient.UploadTools(f, uploadToolsVersion, additionalSeries...)
	if err != nil {
		return errors.Trace(err)
	}
	context.tools = uploaded
	return nil
}
Пример #26
0
// locallyBuildableTools returns the list of tools that
// can be built locally, for series of the same OS.
func locallyBuildableTools() (buildable coretools.List) {
	for _, ser := range series.SupportedSeries() {
		if os, err := series.GetOSFromSeries(ser); err != nil || os != jujuos.HostOS() {
			continue
		}
		binary := version.Binary{
			Number: version.Current.Number,
			Series: ser,
			Arch:   arch.HostArch(),
		}
		// Increment the build number so we know it's a development build.
		binary.Build++
		buildable = append(buildable, &coretools.Tools{Version: binary})
	}
	return buildable
}
Пример #27
0
// ParseBinary parses a binary version of the form "1.2.3-series-arch".
func ParseBinary(s string) (Binary, error) {
	m := binaryPat.FindStringSubmatch(s)
	if m == nil {
		return Binary{}, fmt.Errorf("invalid binary version %q", s)
	}
	var v Binary
	v.Major = atoi(m[1])
	v.Minor = atoi(m[2])
	v.Tag = m[4]
	v.Patch = atoi(m[5])
	if m[6] != "" {
		v.Build = atoi(m[6][1:])
	}
	v.Series = m[7]
	v.Arch = m[8]
	_, err := series.GetOSFromSeries(v.Series)
	return v, err
}
Пример #28
0
Файл: tools.go Проект: bac/juju
// locallyBuildableTools returns the list of tools that
// can be built locally, for series of the same OS.
func locallyBuildableTools(toolsSeries *string) (buildable coretools.List, _ version.Number) {
	buildNumber := jujuversion.Current
	// Increment the build number so we know it's a custom build.
	buildNumber.Build++
	for _, ser := range series.SupportedSeries() {
		if os, err := series.GetOSFromSeries(ser); err != nil || !os.EquivalentTo(jujuos.HostOS()) {
			continue
		}
		if toolsSeries != nil && ser != *toolsSeries {
			continue
		}
		binary := version.Binary{
			Number: buildNumber,
			Series: ser,
			Arch:   arch.HostArch(),
		}
		buildable = append(buildable, &coretools.Tools{Version: binary})
	}
	return buildable, buildNumber
}
Пример #29
0
// New returns a new Config with no options set.
func New(ser string) (CloudConfig, error) {
	seriesos, err := series.GetOSFromSeries(ser)
	if err != nil {
		return nil, err
	}
	switch seriesos {
	case os.Windows:
		renderer, _ := shell.NewRenderer("powershell")
		return &windowsCloudConfig{
			&cloudConfig{
				series:   ser,
				renderer: renderer,
				attrs:    make(map[string]interface{}),
			},
		}, nil
	case os.Ubuntu:
		renderer, _ := shell.NewRenderer("bash")
		return &ubuntuCloudConfig{
			&cloudConfig{
				series:    ser,
				paccmder:  commands.NewAptPackageCommander(),
				pacconfer: config.NewAptPackagingConfigurer(ser),
				renderer:  renderer,
				attrs:     make(map[string]interface{}),
			},
		}, nil
	case os.CentOS:
		renderer, _ := shell.NewRenderer("bash")
		return &centOSCloudConfig{
			&cloudConfig{
				series:    ser,
				paccmder:  commands.NewYumPackageCommander(),
				pacconfer: config.NewYumPackagingConfigurer(ser),
				renderer:  renderer,
				attrs:     make(map[string]interface{}),
			},
		}, nil
	default:
		return nil, errors.NotFoundf("cloudconfig for series %q", ser)
	}
}
Пример #30
0
// newOSDisk creates a gwacl.OSVirtualHardDisk object suitable for an
// Azure Virtual Machine.
func (env *azureEnviron) newOSDisk(sourceImageName string, ser string) (*gwacl.OSVirtualHardDisk, error) {
	vhdName := gwacl.MakeRandomDiskName("juju")
	vhdPath := fmt.Sprintf("vhds/%s", vhdName)
	snap := env.getSnapshot()
	storageAccount := snap.ecfg.storageAccountName()
	mediaLink := gwacl.CreateVirtualHardDiskMediaLink(storageAccount, vhdPath)
	os, err := series.GetOSFromSeries(ser)
	if err != nil {
		return nil, errors.Trace(err)
	}
	var OSType string
	switch os {
	case jujuos.Windows:
		OSType = "Windows"
	default:
		OSType = "Linux"
	}
	// The disk label is optional and the disk name can be omitted if
	// mediaLink is provided.
	return gwacl.NewOSVirtualHardDisk("", "", "", mediaLink, sourceImageName, OSType), nil
}