Giter Site home page Giter Site logo

linux_admin's Introduction

LinuxAdmin

Gem Version CI Code Climate Test Coverage

LinuxAdmin is a module to simplify management of linux systems. It should be a single place to manage various system level configurations, registration, updates, etc.

Installation

Add this line to your application's Gemfile:

gem 'linux_admin'

And then execute:

$ bundle

Or install it yourself as:

$ gem install linux_admin

Usage

TODO: Write usage instructions here

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

linux_admin's People

Contributors

agrare avatar alongoldboim avatar bdunne avatar carbonin avatar chessbyte avatar d-m-u avatar djberg96 avatar duskyprawn avatar fryguy avatar gtanzillo avatar himdel avatar isimluk avatar jrafanie avatar jvlcek avatar kbrock avatar mend-bolt-for-github[bot] avatar movitto avatar nicklamuro avatar renovate[bot] avatar simaishi avatar yrudman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

linux_admin's Issues

LinuxAdmin::Disk.local doesn't work in RHEL6 in AWS

In RHEL6 on AWS, the disk devices show up like this:
/dev/xvda

In disk.rb, line 56, the Dir.glob does't allow for devices to start with 'xv':
Dir.glob('/dev/[vhs]d[a-z]').collect do |d|

Therefore local disks don't show up.

I believe this is broken for all Xen paravirt guests (xvd* is the norm), but I have no way to confirm that.

LinuxAdmin::Disk.create_partition causes parted to exit with a 1

I get an error when I try to create a partition like this:

irb> require 'linux_admin'
=> true

irb> disk = LinuxAdmin::Disk.new(:path => '/dev/xvdp')
=> #<LinuxAdmin::Disk:0x00000001f64108 @path="/dev/xvdp">

irb> disk.create_partition('primary', 1024)
CommandResultError: /sbin/parted exit code: 1
    from /opt/rh/ruby193/root/usr/share/gems/gems/linux_admin-0.7.0/lib/linux_admin/common.rb:41:in `run!'
    from /opt/rh/ruby193/root/usr/share/gems/gems/linux_admin-0.7.0/lib/linux_admin/disk.rb:156:in `create_partition'
    from (irb):3
    from /opt/rh/ruby193/root/usr/bin/irb:12:in `<main>'

irb>

I've tracked this down to this line in disk.rb:
options = parted_options_array('mkpart', '-a opt', partition_type, start, finish)

It should be:
options = parted_options_array('mkpart', '-a', 'opt', partition_type, start, finish)

'-a opt' all together makes the parted command look like this (the slash is the problem):
/sbin/parted --script /dev/xvdp mkpart -a\ opt primary 0 1024

Add a mechanism to return a string containing the command to be run

A mechanism is needed that would provide the caller with a string representing the command to be run. It could be returned from run and run! also returned from a new "what would be run if" method. Where a hash could be passed in, much the way it is to run!, and a string would be returned containing the command that would be run.

[RFE] LinuxAdmin::Hosts API should support removal of hostnames and aliases

Currently LinuxAdmin::Hosts supports #add_alias and #set_canonical_hostname
It should also support #remove_alias #unset_canonical_hostname (method names TBD)

Also currently #set_canonical_hostname, by default, removes the hostname from
all addresses before setting it on only 1. Support to allow users to remove a hostname
from individual addresses but also to allow multiple addresses to be associated with
a single name

Disk#create_partition should align partitions, starting with creating a whole disk partition

The current implementation to create_partition leads me to write the following in order to create a single partition that takes up the whole disk:

disk.create_partition("primary", disk.size.to_i/1.megabyte)

This results in the following parted command, which LinuxAdmin.run doesn't handle correctly because there's input requested due to bad alignment(#39):

# /sbin/parted /dev/sdb mkpart primary 0 1073
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? Cancel

According to this: http://unix.stackexchange.com/questions/38164/create-partition-aligned-using-parted, you can use percentages

Either:

/sbin/parted -s -a opt /dev/sdb mkpart primary 0% 100%

Or:

/sbin/parted -s /dev/sdb mkpart primary 0% 100%

This results in the same thing, bypasses any prompting/errors by parted:

[root@localhost tmp]# parted /dev/sdb print
Model: VMware, VMware Virtual S (scsi)
Disk /dev/sdb: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1074MB  1073MB  primary

`Hosts` class should distinguish between fqdn and aliases

The /etc/hosts man page (http://man7.org/linux/man-pages/man5/hosts.5.html) describes a difference between the "canonical_hostname" (fqdn) and the aliases for that hostname.

The LinuxAdmin::Hosts class should expose that difference in its API. Maybe a method to specifically set the first name in the list and then a separate one that appends to the aliases?

This difference is reflected in the behaviour of some external tools such as cloud-init and freeipa.
These tools will retrieve the hostname (typically via the hostname command or from /etc/hostname) then consult /etc/hosts to find the fqdn by taking the name in the "canonical_hostname" place in the line where the found hostname is an alias.

This can cause problems when the application acts differently based on whether the fqdn is "localhost" or not.

Add optional :logger to LinuxAdmin.run and run!

This should do the following:

  1. rescue any exceptions
  2. log the command, minus any params
  3. log the output as info
  4. log the exit code as error when non-zero
  5. log standard error as error if exit code is non-zero, warn otherwise.
  6. re-raise the existing exception

LinuxAdmin::Disk.local returns non-local disks in Docker container environment

In Docker container, LinuxAdmin::Disk.local returns:

irb(main):001:0> LinuxAdmin::Disk.local
=> [#<LinuxAdmin::Disk:0x00000008fcfb40 @path="/dev/sdb">, #<LinuxAdmin::Disk:0x00000008fcfac8 @path="/dev/sda">, #<LinuxAdmin::Disk:0x00000008fcfa28 @path="/dev/hdd">, #<LinuxAdmin::Disk:0x00000008fcf960 @path="/dev/hdc">, #<LinuxAdmin::Disk:0x00000008fcf7f8 @path="/dev/hdb">, #<LinuxAdmin::Disk:0x00000008fcf758 @path="/dev/hda">]

while fdisk -l just returns /dev/sda

The extra paths reported by LinuxAdmin exists in the image, but not sure where they came from...

brw-rw-r-- 1 root ftp   3,  0 May 10 13:05 /dev/hda
brw-rw-r-- 1 root ftp   3, 64 May 10 13:05 /dev/hdb
brw-rw-r-- 1 root ftp  22,  0 May 10 13:05 /dev/hdc
brw-rw-r-- 1 root ftp  22, 64 May 10 13:05 /dev/hdd
brw-rw---- 1 root disk  8,  0 May 10 13:05 /dev/sda
brw-rw-r-- 1 root ftp   8, 16 May 10 13:05 /dev/sdb

cc @carbonin

Chronyd restart

When adding NTP servers in linux_admin/lib/linux_admin/chrony.rb chronyd should also restarted.

As it currently stands when the add_servers method is called to update the list of servers the service is not restarted. Thus a user needs to manually restart chronyd for the changes to take effect.

LogicalVolume.create should allow for %FREE option

For example, we should use this to avoid specifying specific sizes:
lvcreate -l 100%FREE -n lv vg

irb(main):002:0> disk = LinuxAdmin::Disk.local.select {|d| d.path == "/dev/sdb"}.first
=> #<LinuxAdmin::Disk:0x000000046a2508 @path="/dev/sdb">

irb(main):003:0> partition = disk.partitions.first
=> #<LinuxAdmin::Partition:0x0000000471eb58 @id=1, @size=1125122048.0, @disk=#<LinuxAdmin::Disk:0x000000046a2508 @path="/dev/sdb", @parted_default_options=["--script", "/dev/sdb"], @partitions=[#<LinuxAdmin::Partition:0x0000000471eb58 ...>]>, @fs_type=nil, @start_sector="1049kB", @end_sector=1126170624.0, @partition_type="primary">

irb(main):004:0> pv = LinuxAdmin::PhysicalVolume.create(partition)
=> #<LinuxAdmin::PhysicalVolume:0x00000004f9fae8 @device_name="/dev/sdb1", @volume_group=nil, @size=1125122048.0>

irb(main):005:0> vg = LinuxAdmin::VolumeGroup.create("vg", pv)
=> #<LinuxAdmin::VolumeGroup:0x00000004471e28 @name="vg_data">

It should be easier to determine the size of the logical volume:

irb(main):015:0> begin; lv = LinuxAdmin::LogicalVolume.create("lv", vg, ((disk.size/1.megabyte) - 1.bytes)); rescue => err; puts err.result.inspect; end
#<CommandResult:0x000000051de688 @output="", @error="  Volume group \"vg\" has insufficient free space (255 extents): 268 required.\n", @exit_status=5>
=> nil

irb(main):016:0> begin; lv = LinuxAdmin::LogicalVolume.create("lv", vg, ((disk.size/1.megabyte) - 14.bytes)); rescue => err; puts err.result.inspect; end
#<CommandResult:0x000000052286c0 @output="  Rounding up size to full physical extent 1.04 GiB\n", @error="  Volume group \"vg\" has insufficient free space (255 extents): 265 required.\n", @exit_status=5>
=> nil

It's not simple to use all of the remaining space so you have to guess or calculate the right number:

irb(main):017:0> begin; lv = LinuxAdmin::LogicalVolume.create("lv", vg, ((disk.size/1.megabyte) - 100.bytes)); rescue => err; puts err.result.inspect; end
=> #<LinuxAdmin::LogicalVolume:0x00000004ff7680 @name="lv", @volume_group=#<LinuxAdmin::VolumeGroup:0x00000004471e28 @name="vg">, @sectors=973.0>

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

This repository currently has no open or pending branches.

Detected dependencies

bundler
Gemfile
github-actions
.github/workflows/ci.yaml
  • actions/checkout v4
  • ruby/setup-ruby v1
  • paambaati/codeclimate-action v6

  • Check this box to trigger a request for Renovate to run again on this repository

Linter warnings

Current list of linter warnings under lib:

Inspecting 39 files
...W.....W....W.W..W..WWW..W.......W.W.

Offenses:

lib/linux_admin/deb.rb:5:40: W: [Correctable] Lint/UnusedMethodArgument: Unused method argument - in_description. If it's necessary, use _ or _in_description as an argument name to indicate that it won't be used.
    def self.from_line(apt_cache_line, in_description=false)
                                       ^^^^^^^^^^^^^^
lib/linux_admin/fstab.rb:102:7: W: Lint/MissingSuper: Call super to initialize state of the parent class.
      def initialize ...
      ^^^^^^^^^^^^^^
lib/linux_admin/logical_volume.rb:43:5: W: Lint/MissingSuper: Call super to initialize state of the parent class.
    def initialize(args = {}) ...
    ^^^^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/logical_volume.rb:57:5: W: [Correctable] Lint/UselessAccessModifier: Useless private access modifier.
    private
    ^^^^^^^
lib/linux_admin/logical_volume.rb:59:5: W: Lint/IneffectiveAccessModifier: private (on line 57) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    def self.bytes_to_string(bytes)
    ^^^
lib/linux_admin/logical_volume.rb:71:5: W: [Correctable] Lint/UselessAccessModifier: Useless public access modifier.
    public
    ^^^^^^
lib/linux_admin/network_interface.rb:215:1: W: [Correctable] Lint/NonDeterministicRequireOrder: Sort files before requiring them.
Dir.glob(File.join(File.dirname(__FILE__), "network_interface", "*.rb")).each { |f| require f }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/null_logger.rb:5:5: W: Lint/MissingSuper: Call super to initialize state of the parent class.
    def initialize(*_args) ...
    ^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/physical_volume.rb:22:5: W: Lint/MissingSuper: Call super to initialize state of the parent class.
    def initialize(args = {}) ...
    ^^^^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/registration_system.rb:57:1: W: [Correctable] Lint/NonDeterministicRequireOrder: Sort files before requiring them.
Dir.glob(File.join(File.dirname(__FILE__), "registration_system", "*.rb")).each { |f| require f }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/registration_system/subscription_manager.rb:84:27: W: [Correctable] Lint/UnusedMethodArgument: Unused method argument - options. If it's necessary, use _ or _options as an argument name to indicate that it won't be used.
    def enable_repo(repo, options = nil)
                          ^^^^^^^
lib/linux_admin/registration_system/subscription_manager.rb:92:28: W: [Correctable] Lint/UnusedMethodArgument: Unused method argument - options. If it's necessary, use _ or _options as an argument name to indicate that it won't be used.
    def disable_repo(repo, options = nil)
                           ^^^^^^^
lib/linux_admin/registration_system/subscription_manager.rb:99:19: W: [Correctable] Lint/UnusedMethodArgument: Unused method argument - options. If it's necessary, use _ or _options as an argument name to indicate that it won't be used. You can also write as all_repos(*) if you want the method to accept any arguments but don't care about them.
    def all_repos(options = nil)
                  ^^^^^^^
lib/linux_admin/service.rb:11:7: W: [Correctable] Lint/UselessAccessModifier: Useless private access modifier.
      private
      ^^^^^^^
lib/linux_admin/service.rb:41:1: W: [Correctable] Lint/NonDeterministicRequireOrder: Sort files before requiring them.
Dir.glob(File.join(File.dirname(__FILE__), "service", "*.rb")).each { |f| require f }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lib/linux_admin/volume.rb:3:5: W: [Correctable] Lint/UselessAccessModifier: Useless private access modifier.
    private
    ^^^^^^^
lib/linux_admin/volume.rb:5:5: W: Lint/IneffectiveAccessModifier: private (on line 3) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    def self.process_volume_display_line(line)
    ^^^
lib/linux_admin/volume.rb:13:5: W: [Correctable] Lint/UselessAccessModifier: Useless protected access modifier.
    protected
    ^^^^^^^^^
lib/linux_admin/volume.rb:15:5: W: Lint/IneffectiveAccessModifier: protected (on line 13) does not make singleton methods protected. Use protected inside a class << self block instead.
    def self.scan_volumes(cmd)
    ^^^
lib/linux_admin/yum.rb:90:5: W: [Correctable] Lint/UselessAccessModifier: Useless private access modifier.
    private
    ^^^^^^^
lib/linux_admin/yum.rb:92:5: W: Lint/IneffectiveAccessModifier: private (on line 90) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    def self.parse_repo_dir(dir)
    ^^^
lib/linux_admin/yum.rb:99:5: W: Lint/IneffectiveAccessModifier: private (on line 90) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    def self.parse_repo_file(file)
    ^^^
lib/linux_admin/yum.rb:102:24: W: [Correctable] Lint/UnusedBlockArgument: Unused block argument - name. If it's necessary, use _ or _name as an argument name to indicate that it won't be used.
      content.each do |name, data|
                       ^^^^
lib/linux_admin/yum.rb:107:5: W: Lint/IneffectiveAccessModifier: private (on line 90) does not make singleton methods private. Use private_class_method or private inside a class << self block instead.
    def self.parse_repo_list_output(content)
    ^^^
lib/linux_admin/yum.rb:125:1: W: [Correctable] Lint/NonDeterministicRequireOrder: Sort files before requiring them.
Dir.glob(File.join(File.dirname(__FILE__), "yum", "*.rb")).each { |f| require f }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

39 files inspected, 25 offenses detected, 15 offenses auto-correctable

Change tests to use stub_good_run

In our tests, we currently reference AwesomeSpawn::CommandResult and other internal api classes

It would be great to start using require "awesome_spawn/spec_helper" and methods like stub_good_run

Parted commands should be passed -s option to prevent prompting

This code:

disk.create_partition("primary", disk.size.to_i/1.megabyte)

launches parted like this (note the prompt for confirmation)

# /sbin/parted /dev/sdb mkpart primary 0 1073
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? Cancel

We should pass -s to prevent prompting.

Fix Hakiri issues

It's hard to review PRs because they all appear as failed. Let's see if we can find why Hakiri fails, or just remove Hakiri. cc @carbonin

LinuxAdmin::NetworkInterface.new("name") assumes there a conf file and fails

LinuxAdmin::NetworkInterface.new("interface_name") assumes there is a conf file in
/etc/sysconfig/network-scripts, but this is not always the case.
So it fails with

Errno::ENOENT: No such file or directory @ rb_sysopen - /etc/sysconfig/network-scripts/ifcfg-eth2

I'm running rhel 6.5, and I have an interface named eth2, and it doesn't have a conf file for it (but the network works ok)

VolumeGroup#scan doesn't strip leading whitespace when parsing the name

# vgcreate vg_data /dev/sdb1
  Volume group "vg_data" successfully created

# bundle console
irb(main):001:0> require 'linux_admin'
=> true
irb(main):002:0> vg = LinuxAdmin::VolumeGroup.scan.first
=> #<LinuxAdmin::VolumeGroup:0x00000003178bf0 @name="  vg_data">
irb(main):003:0> vg.name
=> "  vg_data"

This causes LogicalVolume.create to fail:

irb(main):03:0> begin;  LinuxAdmin::LogicalVolume.create("lv_pg", vg, (LinuxAdmin::Disk.local.first.size / 1.megabytes).to_i - 1.megabyte); rescue => err; puts err.result.inspect; end
#<CommandResult:0x00000004f123c8 @output="", @error="  Volume group name   vg_data has invalid characters\n  Run `lvcreate --help' for more information.\n", @exit_status=3>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.