func getHostState(host Host, hostListItemsChan chan<- HostListItem) { currentState, err := host.Driver.GetState() if err != nil { log.Errorf("error getting state for host %s: %s", host.Name, err) } url, err := host.GetURL() if err != nil { if err == drivers.ErrHostIsNotRunning { url = "" } else { log.Errorf("error getting URL for host %s: %s", host.Name, err) } } dockerHost := os.Getenv("DOCKER_HOST") hostListItemsChan <- HostListItem{ Name: host.Name, Active: dockerHost == url && currentState != state.Stopped, DriverName: host.Driver.DriverName(), State: currentState, URL: url, SwarmOptions: *host.HostOptions.SwarmOptions, } }
// IsActive provides a single method for determining if a host is active based // on both the url and if the host is stopped. func (h *Host) IsActive() (bool, error) { currentState, err := h.Driver.GetState() if err != nil { log.Errorf("error getting state for host %s: %s", h.Name, err) return false, err } url, err := h.GetURL() if err != nil { if err == drivers.ErrHostIsNotRunning { url = "" } else { log.Errorf("error getting URL for host %s: %s", h.Name, err) return false, err } } dockerHost := os.Getenv("DOCKER_HOST") notStopped := currentState != state.Stopped correctURL := url == dockerHost isActive := notStopped && correctURL return isActive, nil }
func attemptGetHostState(host Host, stateQueryChan chan<- HostListItem) { currentState, err := host.Driver.GetState() if err != nil { log.Errorf("error getting state for host %s: %s", host.Name, err) } url, err := host.GetURL() if err != nil { if err == drivers.ErrHostIsNotRunning { url = "" } else { log.Errorf("error getting URL for host %s: %s", host.Name, err) } } isActive, err := host.IsActive() if err != nil { log.Errorf("error determining if host is active for host %s: %s", host.Name, err) } stateQueryChan <- HostListItem{ Name: host.Name, Active: isActive, DriverName: host.Driver.DriverName(), State: currentState, URL: url, SwarmOptions: *host.HostOptions.SwarmOptions, } }
func (d *Driver) importVdi(vdi *xsclient.VDI, filename string, timeout time.Duration) error { f, err := os.Open(filename) if err != nil { log.Errorf("Unable to open disk image '%s': %v", filename, err) return err } // Get file length fi, err := f.Stat() if err != nil { log.Errorf("Unable to stat disk image '%s': %v", filename, err) return err } task, err := vdi.Client.CreateTask() if err != nil { return fmt.Errorf("Unable to create task: %v", err) } urlStr := fmt.Sprintf("https://%s/import_raw_vdi?vdi=%s&session_id=%s&task_id=%s", vdi.Client.Host, vdi.Ref, vdi.Client.Session.(string), task.Ref) // Define a new http Transport which allows self-signed certs tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } req, err := http.NewRequest("PUT", urlStr, f) if err != nil { return err } req.ContentLength = fi.Size() resp, err := tr.RoundTrip(req) if err != nil { log.Errorf("Unable to upload VDI: %v", err) return err } defer resp.Body.Close() if resp.StatusCode != 200 { msg, _ := ioutil.ReadAll(resp.Body) err = fmt.Errorf("xenserver reply %s: %v", resp.Status, string(msg)) log.Errorf("Unable to upload VDI: %v", err) return err } log.Infof("Waiting Upload VDI task(%v) to complete...", task.Ref) if err = d.waitTask(task, timeout); err != nil { return err } return nil }
func (d *Driver) Remove() error { if d.InstanceId == "" { return fmt.Errorf("unknown instance") } s, err := d.GetState() if err == nil && s == state.Running { if err := d.Stop(); err != nil { log.Errorf("unable to stop instance: %s", err) } } instance, err := d.getInstance() if err != nil { log.Errorf("unable to describe instance: %s", err) } else { // Check and release EIP if exists if len(instance.EipAddress.AllocationId) != 0 { allocationId := instance.EipAddress.AllocationId err = d.getClient().UnassociateEipAddress(allocationId, instance.InstanceId) if err != nil { log.Errorf("Failed to unassociate EIP address: %v", err) } err = d.getClient().WaitForEip(instance.RegionId, allocationId, ecs.EipStatusAvailable, 0) if err != nil { log.Errorf("Failed to wait EIP %s: %v", allocationId, err) } err = d.getClient().ReleaseEipAddress(allocationId) if err != nil { log.Errorf("Failed to release EIP address: %v", err) } } log.Debugf("instance: %++v\n", instance) log.Debugf("instance.VpcAttributes: %++v\n", instance.VpcAttributes) vpcId := instance.VpcAttributes.VpcId if vpcId != "" { // Remove route entry firstly d.removeRouteEntry(vpcId, instance.RegionId, instance.InstanceId) } } log.Debugf("terminating instance: %s", d.InstanceId) if err := d.getClient().DeleteInstance(d.InstanceId); err != nil { return fmt.Errorf("unable to terminate instance: %s", err) } return nil }
func cmdStatus(c *cli.Context) { host := getHost(c) currentState, err := host.Driver.GetState() if err != nil { log.Errorf("error getting state for host %s: %s", host.Name, err) } log.Info(currentState) }
func RunSSHCommandFromDriver(d Driver, command string) (string, error) { client, err := GetSSHClientFromDriver(d) if err != nil { return "", err } log.Debugf("About to run SSH command:\n%s", command) output, err := client.Output(command) log.Debugf("SSH cmd err, output: %v: %s", err, output) if err != nil && !isErr255Exit(err) { log.Error("SSH cmd error!") log.Errorf("command: %s", command) log.Errorf("err : %v", err) log.Fatalf("output : %s", output) } return output, err }
func (d *Driver) UpgradeISO() error { vcConn := NewVcConn(d) if _, err := os.Stat(d.ISO); os.IsNotExist(err) { log.Errorf("Unable to find boot2docker ISO at %s", d.ISO) return errors.NewIncompleteVsphereConfigError(d.ISO) } if err := vcConn.DatastoreUpload(d.ISO, d.MachineName); err != nil { return err } return nil }
func (s Filestore) List() ([]*Host, error) { dir, err := ioutil.ReadDir(utils.GetMachineDir()) if err != nil && !os.IsNotExist(err) { return nil, err } hosts := []*Host{} for _, file := range dir { // don't load hidden dirs; used for configs if file.IsDir() && strings.Index(file.Name(), ".") != 0 { host, err := s.Get(file.Name()) if err != nil { log.Errorf("error loading host %q: %s", file.Name(), err) continue } hosts = append(hosts, host) } } return hosts, nil }
func cmdRm(c *cli.Context) { if len(c.Args()) == 0 { cli.ShowCommandHelp(c, "rm") log.Fatal("You must specify a machine name") } force := c.Bool("force") isError := false certInfo := getCertPathInfo(c) defaultStore, err := getDefaultStore( c.GlobalString("storage-path"), certInfo.CaCertPath, certInfo.CaKeyPath, ) if err != nil { log.Fatal(err) } mcn, err := newMcn(defaultStore) if err != nil { log.Fatal(err) } for _, host := range c.Args() { if err := mcn.Remove(host, force); err != nil { log.Errorf("Error removing machine %s: %s", host, err) isError = true } else { log.Infof("Successfully removed %s", host) } } if isError { log.Fatal("There was an error removing a machine. To force remove it, pass the -f option. Warning: this might leave it running on the provider.") } }
func (d *Driver) GetImageID(image string) string { if len(image) != 0 { return image } args := ecs.DescribeImagesArgs{ RegionId: d.Region, ImageOwnerAlias: ecs.ImageOwnerSystem, } // Scan registed images with prefix of ubuntu1404_64_20G_ for { images, pagination, err := d.getClient().DescribeImages(&args) if err != nil { log.Errorf("Failed to describe images: %v", err) break } else { for _, image := range images { if strings.HasPrefix(image.ImageId, defaultUbuntuImagePrefix) { return image.ImageId } } nextPage := pagination.NextPage() if nextPage == nil { break } args.Pagination = *nextPage } } //Default use the config Ubuntu 14.04 64bits image image = defaultUbuntuImageID return image }
func cmdCreate(c *cli.Context) { var ( err error ) driver := c.String("driver") name := c.Args().First() // TODO: Not really a fan of "none" as the default driver... if driver != "none" { c.App.Commands, err = trimDriverFlags(driver, c.App.Commands) if err != nil { log.Fatal(err) } } if name == "" { cli.ShowCommandHelp(c, "create") log.Fatal("You must specify a machine name") } if err := validateSwarmDiscovery(c.String("swarm-discovery")); err != nil { log.Fatalf("Error parsing swarm discovery: %s", err) } certInfo := getCertPathInfo(c) if err := setupCertificates( certInfo.CaCertPath, certInfo.CaKeyPath, certInfo.ClientCertPath, certInfo.ClientKeyPath); err != nil { log.Fatalf("Error generating certificates: %s", err) } defaultStore, err := getDefaultStore( c.GlobalString("storage-path"), certInfo.CaCertPath, certInfo.CaKeyPath, ) if err != nil { log.Fatal(err) } provider, err := newProvider(defaultStore) if err != nil { log.Fatal(err) } hostOptions := &libmachine.HostOptions{ AuthOptions: &auth.AuthOptions{ CaCertPath: certInfo.CaCertPath, PrivateKeyPath: certInfo.CaKeyPath, ClientCertPath: certInfo.ClientCertPath, ClientKeyPath: certInfo.ClientKeyPath, ServerCertPath: filepath.Join(utils.GetMachineDir(), name, "server.pem"), ServerKeyPath: filepath.Join(utils.GetMachineDir(), name, "server-key.pem"), }, EngineOptions: &engine.EngineOptions{ ArbitraryFlags: c.StringSlice("engine-opt"), Env: c.StringSlice("engine-env"), InsecureRegistry: c.StringSlice("engine-insecure-registry"), Labels: c.StringSlice("engine-label"), RegistryMirror: c.StringSlice("engine-registry-mirror"), StorageDriver: c.String("engine-storage-driver"), TlsVerify: true, InstallURL: c.String("engine-install-url"), }, SwarmOptions: &swarm.SwarmOptions{ IsSwarm: c.Bool("swarm"), Image: c.String("swarm-image"), Master: c.Bool("swarm-master"), Discovery: c.String("swarm-discovery"), Address: c.String("swarm-addr"), Host: c.String("swarm-host"), Strategy: c.String("swarm-strategy"), ArbitraryFlags: c.StringSlice("swarm-opt"), }, } _, err = provider.Create(name, driver, hostOptions, c) if err != nil { log.Errorf("Error creating machine: %s", err) log.Fatal("You will want to check the provider to make sure the machine and associated resources were properly removed.") } info := fmt.Sprintf("%s env %s", c.App.Name, name) log.Infof("To see how to connect Docker to this machine, run: %s", info) }
// the current implementation does the following: // 1. check whether the docker directory contains the boot2docker ISO // 2. generate an SSH keypair and bundle it in a tar. // 3. create a virtual machine with the boot2docker ISO mounted; // 4. reconfigure the virtual machine network and disk size; func (d *Driver) Create() error { if err := d.checkVsphereConfig(); err != nil { return err } b2dutils := utils.NewB2dUtils("", "") if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Generating SSH Keypair...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } vcConn := NewVcConn(d) log.Infof("Uploading Boot2docker ISO ...") if err := vcConn.DatastoreMkdir(d.MachineName); err != nil { return err } if _, err := os.Stat(d.ISO); os.IsNotExist(err) { log.Errorf("Unable to find boot2docker ISO at %s", d.ISO) return errors.NewIncompleteVsphereConfigError(d.ISO) } if err := vcConn.DatastoreUpload(d.ISO, d.MachineName); err != nil { return err } isoPath := fmt.Sprintf("%s/%s", d.MachineName, isoFilename) if err := vcConn.VMCreate(isoPath); err != nil { return err } log.Infof("Configuring the virtual machine %s... ", d.MachineName) if err := vcConn.VMDiskCreate(); err != nil { return err } if err := vcConn.VMAttachNetwork(); err != nil { return err } if err := d.Start(); err != nil { return err } // Generate a tar keys bundle if err := d.generateKeyBundle(); err != nil { return err } // Copy SSH keys bundle if err := vcConn.GuestUpload(B2DUser, B2DPass, path.Join(d.storePath, "userdata.tar"), "/home/docker/userdata.tar"); err != nil { return err } // Expand tar file. if err := vcConn.GuestStart(B2DUser, B2DPass, "/usr/bin/sudo", "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && /usr/bin/sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && /usr/bin/sudo chown -R docker:staff /home/docker"); err != nil { return err } return nil }
func (d *Driver) removeRouteEntry(vpcId string, regionId ecs.Region, instanceId string) error { client := d.getClient() describeArgs := ecs.DescribeVpcsArgs{ VpcId: vpcId, RegionId: regionId, } vpcs, _, err := client.DescribeVpcs(&describeArgs) if err != nil { return fmt.Errorf("Failed to describe VPC %s in region %s: %v", d.VpcId, d.Region, err) } vrouterId := vpcs[0].VRouterId describeRouteTablesArgs := ecs.DescribeRouteTablesArgs{ VRouterId: vrouterId, } count := 0 for { found := false routeTables, _, err := client.DescribeRouteTables(&describeRouteTablesArgs) if err != nil { return fmt.Errorf("Failed to describe route tables: %v", err) } routeEntries := routeTables[0].RouteEntrys.RouteEntry // Fine route entry associated with instance for _, routeEntry := range routeEntries { log.Debugf("Route Entry %++v\n", routeEntry) if routeEntry.InstanceId == instanceId { found = true deleteArgs := ecs.DeleteRouteEntryArgs{ RouteTableId: routeEntry.RouteTableId, DestinationCidrBlock: routeEntry.DestinationCidrBlock, NextHopId: routeEntry.InstanceId, } err := client.DeleteRouteEntry(&deleteArgs) if err != nil { log.Errorf("Failed to delete route entry: %v", err) } break } } if found { // Wait route entry be removed count++ if count <= _MAX_RETRY { time.Sleep(5 * time.Second) } else { return fmt.Errorf("Failed to delete route entry after %d times", _MAX_RETRY) } } else { break } } return nil }
func (d *Driver) Create() error { var err error d.setMachineNameIfNotSet() // Download boot2docker ISO from Internet b2dutils := utils.NewB2dUtils("", "", isoFilename) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Logging into XenServer %s...", d.Server) c, err := d.GetXenAPIClient() if err != nil { return err } // Generate SSH Keys log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Infof("Creating ISO VDI...") // Get the SR var sr *xsclient.SR if d.SR == "" { sr, err = c.GetDefaultSR() } else { sr, err = c.GetUniqueSRByNameLabel(d.SR) } if err != nil { return err } isoFileInfo, err := os.Stat(d.ISO) if err != nil { return err } // Create the VDI isoVdi, err := sr.CreateVdi(isoFilename, isoFileInfo.Size()) if err != nil { log.Errorf("Unable to create ISO VDI '%s': %v", isoFilename, err) return err } // Import the VDI if err = d.importVdi(isoVdi, d.ISO, time.Duration(d.UploadTimeout)*time.Second); err != nil { return err } isoVdiUuid, err := isoVdi.GetUuid() if err != nil { return err } log.Infof("Creating Disk VDI...") err = d.generateDiskImage() if err != nil { return err } // Create the VDI diskVdi, err := sr.CreateVdi("bootdocker disk", int64(d.DiskSize)*1024*1024) if err != nil { log.Errorf("Unable to create ISO VDI '%s': %v", "bootdocker disk", err) return err } if err = d.importVdi(diskVdi, d.TAR, time.Duration(d.UploadTimeout)*time.Second); err != nil { return err } diskVdiUuid, err := diskVdi.GetUuid() if err != nil { return err } log.Infof("Creating VM...") vm0, err := c.GetUniqueVMByNameLabel(osTemplateLabelName) if err != nil { return err } // Clone VM from VM template vm, err := vm0.Clone(fmt.Sprintf("__gui__%s", d.MachineName)) if err != nil { return err } vmMacSeed, err := pseudoUuid() if err != nil { return err } hostname, err := os.Hostname() if err != nil { log.Errorf("Unable get local hostname") } otherConfig := map[string]string{ "base_template_name": osTemplateLabelName, "install-methods": "cdrom,nfs,http,ftp", "linux_template": "true", "mac_seed": vmMacSeed, "docker-machine-creator": hostname, } err = vm.SetOtherConfig(otherConfig) if err != nil { return err } log.Infof("Provision VM...") err = vm.Provision() if err != nil { return err } // Set machine name err = vm.SetNameLabel(d.MachineName) if err != nil { return err } // Set vCPU number err = vm.SetVCPUsMax(d.CPU) if err != nil { return err } err = vm.SetVCPUsAtStartup(d.CPU) if err != nil { return err } platform_params := map[string]string{ "acpi": "1", "apic": "true", "cores-per-socket": "1", "device_id": "0001", "nx": "true", "pae": "true", "vga": "std", "videoram": "8", "viridian": "false", } err = vm.SetPlatform(platform_params) if err != nil { return err } // Set machine memory size err = vm.SetStaticMemoryRange(uint64(d.Memory)*1024*1024, uint64(d.Memory)*1024*1024) if err != nil { return err } log.Infof("Add ISO VDI to VM...") diskVdi, err = c.GetVdiByUuid(isoVdiUuid) if err != nil { return err } err = vm.ConnectVdi(diskVdi, xsclient.Disk, "0") if err != nil { return err } log.Infof("Add Disk VDI to VM...") diskVdi, err = c.GetVdiByUuid(diskVdiUuid) if err != nil { return err } err = vm.ConnectVdi(diskVdi, xsclient.Disk, "1") if err != nil { return err } log.Infof("Add Network to VM...") var networks []*xsclient.Network if d.Network == "" { networks1, err := c.GetNetworks() if err != nil { return err } for _, network := range networks1 { otherConfig, err := network.GetOtherConfig() if err != nil { return err } isInternal, ok := otherConfig["is_host_internal_management_network"] if ok && isInternal == "true" { continue } automaitc, ok := otherConfig["automatic"] if ok && automaitc == "false" { continue } networks = append(networks, network) } } else { network, err := c.GetUniqueNetworkByNameLabel(d.Network) if err != nil { return err } networks = append(networks, network) } if len(networks) == 0 { return fmt.Errorf("Unable get available networks for %v", d.MachineName) } vifDevices, err := vm.GetAllowedVIFDevices() if err != nil { return err } if len(vifDevices) < len(networks) { log.Warnf("VM(%s) networks number is limited to %d.", d.MachineName, len(vifDevices)) networks = networks[:len(vifDevices)] } for i, network := range networks { _, err = vm.ConnectNetwork(network, vifDevices[i]) if err != nil { return err } } log.Infof("Starting VM...") if d.Host == "" { if err = vm.Start(false, false); err != nil { return err } } else { host, err := c.GetUniqueHostByNameLabel(d.Host) if err != nil { return err } if err = vm.StartOn(host, false, false); err != nil { return err } } if err := d.wait(time.Duration(d.WaitTimeout) * time.Second); err != nil { return err } log.Infof("VM Created.") return nil }