// doNsenterMount nsenters the host's mount namespace and performs the // requested mount. func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { glog.V(5).Infof("nsenter Mounting %s %s %s %v", source, target, fstype, options) args := n.makeNsenterArgs(source, target, fstype, options) glog.V(5).Infof("Mount command: %v %v", nsenterPath, args) exec := exec.New() outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() if len(outputBytes) != 0 { glog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes)) } return err }
// Unmount runs umount(8) in the host's mount namespace. func (n *NsenterMounter) Unmount(target string) error { args := []string{ "--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("umount"), target, } glog.V(5).Infof("Unmount command: %v %v", nsenterPath, args) exec := exec.New() outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() if len(outputBytes) != 0 { glog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes)) } return err }
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt // in the host's root mount namespace. func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { file, err := filepath.Abs(file) if err != nil { return true, err } // Check the directory exists if _, err = os.Stat(file); os.IsNotExist(err) { glog.V(5).Infof("findmnt: directory %s does not exist", file) return true, err } // Add --first-only option: since we are testing for the absense of a mountpoint, it is sufficient to get only // the first of multiple possible mountpoints using --first-only. // Also add fstype output to make sure that the output of target file will give the full path // TODO: Need more refactoring for this function. Track the solution with issue #26996 args := []string{"--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("findmnt"), "-o", "target,fstype", "--noheadings", "--first-only", "--target", file} glog.V(5).Infof("findmnt command: %v %v", nsenterPath, args) exec := exec.New() out, err := exec.Command(nsenterPath, args...).CombinedOutput() if err != nil { glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err) // Different operating systems behave differently for paths which are not mount points. // On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/". // It's safer to assume that it's not a mount point. return true, nil } mountTarget := strings.Split(string(out), " ")[0] mountTarget = strings.TrimSuffix(mountTarget, "\n") glog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v:", file, mountTarget) if mountTarget == file { glog.V(5).Infof("IsLikelyNotMountPoint: %s is a mount point", file) return false, nil } glog.V(5).Infof("IsLikelyNotMountPoint: %s is not a mount point", file) return true, nil }
func NewPlugin(networkPluginDir string) network.NetworkPlugin { protocol := utiliptables.ProtocolIpv4 execer := utilexec.New() dbus := utildbus.New() iptInterface := utiliptables.New(execer, dbus, protocol) return &kubenetNetworkPlugin{ podIPs: make(map[kubecontainer.ContainerID]string), MTU: 1460, //TODO: don't hardcode this execer: utilexec.New(), iptables: iptInterface, vendorDir: networkPluginDir, hostportHandler: hostport.NewHostportHandler(), nonMasqueradeCIDR: "10.0.0.0/8", } }
func (plugin *execNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, error) { out, err := utilexec.New().Command(plugin.getExecutable(), statusCmd, namespace, name, id.ID).CombinedOutput() glog.V(5).Infof("Status 'exec' network plugin output: %s, %v", string(out), err) if err != nil { return nil, err } if string(out) == "" { return nil, nil } findVersion := struct { unversioned.TypeMeta `json:",inline"` }{} err = json.Unmarshal(out, &findVersion) if err != nil { return nil, err } // check kind and version if findVersion.Kind != "" && findVersion.Kind != "PodNetworkStatus" { errStr := fmt.Sprintf("Invalid 'kind' returned in network status for pod '%s'. Valid value is 'PodNetworkStatus', got '%s'.", name, findVersion.Kind) return nil, errors.New(errStr) } switch findVersion.APIVersion { case "": fallthrough case "v1beta1": networkStatus := &network.PodNetworkStatus{} err = json.Unmarshal(out, networkStatus) return networkStatus, err } errStr := fmt.Sprintf("Unknown version '%s' in network status for pod '%s'.", findVersion.APIVersion, name) return nil, errors.New(errStr) }
func (attacher *gcePersistentDiskAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error { // Only mount the PD globally once. mounter := attacher.host.GetMounter() notMnt, err := mounter.IsLikelyNotMountPoint(deviceMountPath) if err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(deviceMountPath, 0750); err != nil { return err } notMnt = true } else { return err } } volumeSource, readOnly, err := getVolumeSource(spec) if err != nil { return err } options := []string{} if readOnly { options = append(options, "ro") } if notMnt { diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Runner: exec.New()} err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, options) if err != nil { os.Remove(deviceMountPath) return err } glog.V(4).Infof("formatting spec %v devicePath %v deviceMountPath %v fs %v with options %+v", spec.Name(), devicePath, deviceMountPath, volumeSource.FSType, options) } return nil }
// Calls "udevadm trigger --action=change" on the specified drive. // drivePath must be the the block device path to trigger on, in the format "/dev/sd*", or a symlink to it. // This is workaround for Issue #7972. Once the underlying issue has been resolved, this may be removed. func udevadmChangeToDrive(drivePath string) error { glog.V(5).Infof("udevadmChangeToDrive: drive=%q", drivePath) // Evaluate symlink, if any drive, err := filepath.EvalSymlinks(drivePath) if err != nil { return fmt.Errorf("udevadmChangeToDrive: filepath.EvalSymlinks(%q) failed with %v.", drivePath, err) } glog.V(5).Infof("udevadmChangeToDrive: symlink path is %q", drive) // Check to make sure input is "/dev/sd*" if !strings.Contains(drive, diskSDPath) { return fmt.Errorf("udevadmChangeToDrive: expected input in the form \"%s\" but drive is %q.", diskSDPattern, drive) } // Call "udevadm trigger --action=change --property-match=DEVNAME=/dev/sd..." _, err = exec.New().Command( "udevadm", "trigger", "--action=change", fmt.Sprintf("--property-match=DEVNAME=%s", drive)).CombinedOutput() if err != nil { return fmt.Errorf("udevadmChangeToDrive: udevadm trigger failed for drive %q with %v.", drive, err) } return nil }
// search /sys/bus for rbd device that matches given pool and image func getDevFromImageAndPool(pool, image string) (string, bool) { // /sys/bus/rbd/devices/X/name and /sys/bus/rbd/devices/X/pool sys_path := "/sys/bus/rbd/devices" if dirs, err := ioutil.ReadDir(sys_path); err == nil { for _, f := range dirs { // pool and name format: // see rbd_pool_show() and rbd_name_show() at // https://github.com/torvalds/linux/blob/master/drivers/block/rbd.c name := f.Name() // first match pool, then match name po := path.Join(sys_path, name, "pool") img := path.Join(sys_path, name, "name") exe := exec.New() out, err := exe.Command("cat", po, img).CombinedOutput() if err != nil { continue } matched, err := regexp.MatchString("^"+pool+"\n"+image+"\n$", string(out)) if err != nil || !matched { continue } // found a match, check if device exists devicePath := "/dev/rbd" + name if _, err := os.Lstat(devicePath); err == nil { return devicePath, true } } } return "", false }
// FIXME: this method can be further pruned. func (attacher *awsElasticBlockStoreAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error { mounter := attacher.host.GetMounter() notMnt, err := mounter.IsLikelyNotMountPoint(deviceMountPath) if err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(deviceMountPath, 0750); err != nil { return err } notMnt = true } else { return err } } volumeSource, readOnly, err := getVolumeSource(spec) if err != nil { return err } options := []string{} if readOnly { options = append(options, "ro") } if notMnt { diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Runner: exec.New()} err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, options) if err != nil { os.Remove(deviceMountPath) return err } } return nil }
func (plugin *execNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string) error { err := plugin.validate() if err != nil { return err } plugin.host = host // call the init script out, err := utilexec.New().Command(plugin.getExecutable(), initCmd).CombinedOutput() glog.V(5).Infof("Init 'exec' network plugin output: %s, %v", string(out), err) return err }
func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, vendorCNIDirPrefix string) []network.NetworkPlugin { configList := make([]network.NetworkPlugin, 0) network, err := getDefaultCNINetwork(pluginDir, vendorCNIDirPrefix) if err != nil { return configList } return append(configList, &cniNetworkPlugin{ defaultNetwork: network, execer: utilexec.New(), }) }
func probeAttachedVolume() error { executor := exec.New() args := []string{"trigger"} cmd := executor.Command("/usr/bin/udevadm", args...) _, err := cmd.CombinedOutput() if err != nil { glog.Errorf("error running udevadm trigger %v\n", err) return err } glog.V(4).Infof("Successfully probed all attachments") return nil }
func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { source, _ := plugin.getGlusterVolumeSource(spec) ep_name := source.EndpointsName ns := pod.Namespace ep, err := plugin.host.GetKubeClient().Core().Endpoints(ns).Get(ep_name) if err != nil { glog.Errorf("glusterfs: failed to get endpoints %s[%v]", ep_name, err) return nil, err } glog.V(1).Infof("glusterfs: endpoints %v", ep) return plugin.newMounterInternal(spec, ep, pod, plugin.host.GetMounter(), exec.New()) }
func (plugin *NoopNetworkPlugin) Init(host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string) error { // Set bridge-nf-call-iptables=1 to maintain compatibility with older // kubernetes versions to ensure the iptables-based kube proxy functions // correctly. Other plugins are responsible for setting this correctly // depending on whether or not they connect containers to Linux bridges // or use some other mechanism (ie, SDN vswitch). // Ensure the netfilter module is loaded on kernel >= 3.18; previously // it was built-in. utilexec.New().Command("modprobe", "br-netfilter").CombinedOutput() if err := utilsysctl.SetSysctl(sysctlBridgeCallIptables, 1); err != nil { glog.Warningf("can't set sysctl %s: %v", sysctlBridgeCallIptables, err) } return nil }
// NewUnmounter is the unmounter routine to clean the volume. func (plugin *flexVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { return plugin.newUnmounterInternal(volName, podUID, &flexVolumeUtil{}, plugin.host.GetMounter(), exec.New()) }
// NewMounter is the mounter routine to build the volume. func (plugin *flexVolumePlugin) NewMounter(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { fv, _, err := getVolumeSource(spec) if err != nil { return nil, err } secrets := make(map[string]string) if fv.SecretRef != nil { kubeClient := plugin.host.GetKubeClient() if kubeClient == nil { return nil, fmt.Errorf("Cannot get kube client") } secretName, err := kubeClient.Core().Secrets(pod.Namespace).Get(fv.SecretRef.Name) if err != nil { err = fmt.Errorf("Couldn't get secret %v/%v err: %v", pod.Namespace, fv.SecretRef, err) return nil, err } for name, data := range secretName.Data { secrets[name] = base64.StdEncoding.EncodeToString(data) glog.V(1).Infof("found flex volume secret info: %s", name) } } return plugin.newMounterInternal(spec, pod, &flexVolumeUtil{}, plugin.host.GetMounter(), exec.New(), secrets) }
func (plugin *execNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error { out, err := utilexec.New().Command(plugin.getExecutable(), tearDownCmd, namespace, name, id.ID).CombinedOutput() glog.V(5).Infof("TearDownPod 'exec' network plugin output: %s, %v", string(out), err) return err }
// This is the primary entrypoint for volume plugins. func ProbeVolumePlugins() []volume.VolumePlugin { return []volume.VolumePlugin{&glusterfsPlugin{nil, exec.New()}} }
// NewFlannelHelper creates a new flannel helper. func NewFlannelHelper() *FlannelHelper { return &FlannelHelper{ subnetFile: flannelSubnetFile, iptablesHelper: utiliptables.New(utilexec.New(), utildbus.New(), utiliptables.ProtocolIpv4), } }