Saturday, September 16, 2017

Working with Chef

Idea is to explore Chef and it's working, in order to do so was trying to deploy Zabbix monitoring tool,  Hence main focus is to check more on Chef instead of Zabbix tool.

Zabbix is another tool for monitoring Server / Devices in the network, the basic idea is simple there will be one server responsible for collecting, storing, analyzing and reporting various data points and there will be an agent which needs to install on each of Server / VMs which we need to monitor. Now the best part is its claim that data points are huge set starting from simple CPU / Memory to file and n/w throughput. This essentially allows multiple possibilities.

Server installation though was straightforward there was still some issue, even-though eventually it did turn on not sure how last error got resolved.

Zabbix server consists of Database and Front-end module, For this demo we used MySQL.

To try out the complete scenario I'm using RHEL 7.1 installed as VM using Oracle Virtual box.

Since will need connectivity to the Internet and some time VPN is essential I always prefer dual network setup,  First is NAT and second is a Host-Only adapter.

Even for NAT, I'm using DHCP server, Same goes with 'Host-Only adapter'.






Zabbix Server installation Instructions:
1.       Add Zabbix Repo
2.       Install packages
yum install zabbix-server-mysql zabbix-web-mysql
 Since Centos 7 doesn’t install mysql by default we will have to do it
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm
yum update
sudo yum install mysql-server
sudo systemctl start mysqld
To get required access
sudo mysql_secure_installation
3.       Configure MySQL
shell> mysql -uroot -p<root_password>
mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> grant all privileges on zabbix.* to zabbix@localhost identified by '<password>';
mysql> quit;

Issues
Here comes big issue, post-deployment Front-end was not coming up
1.       Recheck MySQL connectivity, SELinux, and firewall
Post restart service came up, still not sure what was issue
2.       Once Front end comes up it check pre-requisites
Issue over there was php modules were not getting loaded.
Ideally php.ini should include installed modules but that was not case,
Hence added following data in file manually
[root@zabbsrv ~]# cat /etc/php.ini
extension=mysql.so
extension=mysqli.so
extension=bcmath.so
extension=mbstring.so
extension=gd.so
extension=dom.so
extension=xmlwriter.so
extension=xmlreader.so
extension=ldap.so



Writing actual Chef Code
Chef generate cookbook zabbix_agent
This generate skeleton for our code now we can go ahead and add some recipes
Here is my receipes/default.rb
include_recipe "#{cookbook_name}::pre-req"
That’s it
For my pre-req file have tried couple of different items:
1.       Using bash:
bash 'install_something' do
  user 'root'
  cwd '/tmp'
  code <<-EOH
  rm -rf /tmp/test.err
  rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm >>/tmp/test.foo 2>>/tmp/test.err
  grep "is already installed" /tmp/test.err
  EOH
  #ignore_failure true
end

2.       Using yum repo
yum_repository 'zabbix' do
  description "Zabbix repo"
  baseurl zabbix_repo
  gpgkey zabbix_gpg
  action :create
end
3.       Using rpm
rpm_package 'zabbix-release' do
        allow_downgrade false
        action :upgrade
        #source 'http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm'
        source zabbix_rpm
end

yum_package 'zabbix-agent' do
        allow_downgrade false
        action :upgrade
end
To test these have used chef-solo, by creating knife.rb file.

Rpm method looks simple and easy,
Here is brief description on chef
In chef all actions are performed on resources, e.g. rpm_pacakge is resource type.
Action we will perform on it will be ‘upgrade’
Its source is ‘<actual location>’

Core coding will be if we work on resource which is not their however basic resource list is quite huge
https://docs.chef.io/resource.html
                                



Saturday, November 5, 2016

Working with Django

Today I was trying tutorial from django here is basic reference of it : https://docs.djangoproject.com/en/1.10/intro/tutorial04/

Here is how my detail.html was looking













Just to ensure that I have learned stuff and not copied, Have added few more scenarios:

1. Let's add current vote values over here,  Not much value addition but worth try.
   This is pretty straight forward, will simply add another label with value as Votes instead of choicename
   Our original code is
<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

  To solve we just copy line for choice_text and replace it with choice.votes (remember that s, and do remove that breakline so that it looks neat)
  So new code becomes:

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label>
    <label for="choice{{ forloop.counter }}">{{ choice.votes}}</label><br />

{% endfor %}
<input type="submit" value="Vote" />
</form>


Which looks like

See votes 3, 5 are added. Let's format them so we know what's it;s

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">`{{ choice.choice_text }}` <i> with Current votes <u> {{choice.votes}} </u>
    </i> </label> <br/>
{% endfor %}
<input type="submit" value="Vote" />

</form>


Here is output:
2. Let's replace these radio buttons with check boxes.
   That's even simpler modify type as "checkbox" instead of radio,  but results are not as expected. 
   
    Did you catch that, yes only `Midnoght` is getting incremented, that's code is only get last choice and not all choices, :(

    Let's see what's happening, in django details.html is only loading page but core work of adding is done by our view .

mysites/polls/view.py

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.

        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

Problem is with request.POST['choice'], it's only reading last choice ignoring earlier once, Solution is to replace request.POST['choice'] with request.POST.getlist('choice').
Notice that change from square brackets to round once, this is because we were using dictionary with key as 'choice' now instead of dict we are calling function of Python getlist hence round brackets.


But now that won't solve complete issue
Here is error we are getting:

 If we scroll down we see actual issue:















Problem is we were passing array to function question.choic_set.get().  So we just write a for loop which will iterate over array and save each value



def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        for selected_choice_pk in request.POST.getlist('choice'):
            selected_choice = question.choice_set.get(pk=selected_choice_pk)
            selected_choice.votes += 1
            selected_choice.save()
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))


Wow issue resolved


Update:

 Found issue original code was return such that if no choices are selected error  is raise, with our changes it's not getting in.

Solution:

First add dummy call to check if they are any return values: request.POST.getlist('choice')[0]
What will this do is raise a IndexError then So we simply catch it :

    except (KeyError, Choice.DoesNotExist, IndexError) as e:
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })

Also we can delete our earlier enhancement #1 once result page is there


Few more update: 

  Another issue, what if there are no choices for given Question,

Solution #1: Check if choices are there if not provide back link

 This is just simple if else and URL tags
{% if question.choice_set.count > 0 %}
    <form action="{% url 'polls:vote' question.id %}" method="post">
    {% for choice in question.choice_set.all %}
        <input type="checkbox" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
        <label for="choice{{ forloop.counter }}">`{{ choice.choice_text }}` </label> <br/>
    {% endfor %}
    <input type="submit" value="Vote" />
    </form>
{% else %}
    <p> <strong style="color:RED;"> Error there are no choices availabe for given question, Report to admin to add choices</strong>
         <a href="{{request.META.HTTP_REFERER}}">Go back</a> or <a href="{% url 'polls:index' %}"> Go to Index </a>

{% endif %}

Solution #2: Modify Index to show only questions with Choices else don't show them at all / show with Mark saying there are no choices 

 






Saturday, November 14, 2015

Openstack Liberty



Thought to give time for Openstack Latest version Liberty:

Here it goes,

First good thing is minimum node requirement is just 2, Compute and Controller no neutron :), So let's boot up two machines and begin.

For controller I used vm with 8GB ram and 100GB storage and 16 for compute, both running CentOS 7.


It's all easy for centos 

yum install centos-release-openstack-liberty
yum install python-openstackclient
yum install openstack-selinux

of course for local setup ntpd  
yum install ntpd
systemctl ntpd start
systemctl enable ntpd

Next is for controller SQL 
yum install mariadb mariadb-server python2-PyMySQL

Here I faced issues with mariadb Aria engine, To begin with error was:
151109 11:02:22 [ERROR] mysqld: Aria engine: log initialization failed
151109 11:02:22 [ERROR] Plugin 'Aria' init function returned error.
151109 11:02:22 [ERROR] Plugin 'Aria' registration as a STORAGE ENGINE failed.
151109 11:02:22 [Note] Plugin 'FEEDBACK' is disabled.
151109 11:02:22 [ERROR] mysqld: Can't find file: './mysql/plugin.frm' (errno: 13)
151109 11:02:22 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
151109 11:02:22 [ERROR] Aria engine is not enabled or did not start. The Aria engine must be enabled to continue as mysqld was configured with --with-aria-tmp-tables
151109 11:02:22 [ERROR] Aborting


Solution I found was
Modify /etc/my.cnf.d/server.cnf  to include following lines:
[mysqld]
bind-address = a.b.c.d

default-storage-engine = innodb
innodb_file_per_table
collation-server = utf8_general_ci
init-connect = 'SET NAMES utf8'
character-set-server = utf8

Then Delete everything in /var/lib/mysql
mysql_install_db  --user=mysql --data=/var/lib/mysql --basedir=/usr

Now check again and it’s working this time
systemctl restart mariadb.service

cat /var/log/mariadb/mariadb.log
Version: '5.5.44-MariaDB'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MariaDB Server

Make sure to eanable mariadb service
# systemctl enable mariadb.service

Next one was NoSQL Mongo DB
yum install mongodb-server mongodb
# systemctl enable mongod.service
# systemctl start mongod.service

Next RabbitMQ
yum install rabbitmq-server
systemctl enable rabbitmq-server.service
systemctl start rabbitmq-server.service

Once basic things are done it’s all about specific services Keystone, Compute, Neutron and Horizon

Issue in Keystone:
No oslo configured
[root@liberty_ctrl ~]# su -s /bin/sh -c "keystone-manage db_sync" keystone
No handlers could be found for logger "oslo_config.cfg"
For now I just removed log setting verbose to false,
Later on it turns out it didn’t make complete job
Reason being MySQL user keystone was not able to login via FQDN, hence added that entry manually
Also it didn’t work of using default token as ‘ADMIN_TOKEN’ had to be hexadecimal value of required length

Only issue I found on documentation is it uses controller keyword many times which needs to be replaced with correct hostname





Other issues:

    Issue #1: Since removal of setup command from CentOS 7 how to set hostname?
                   Here is new command: "hostnamectl set-hostname liberty_ctrl"

    Issue #2: I missed to allocate size correctly at beginning:

                   Here are steps to I used to increase partition:
                   parted -a optimal /dev/sdb -- mkpart primary 68.7GB 100%
                   parted /dev/sdb -- toggle 2 lvm
                 
                   vgextend vg1 /dev/sdb2
                   lvextend /dev/vg1/root -l +100%FREE
             
               
                  resize2fs /dev/vg1/root


                   

Saturday, November 7, 2015

OpenVPN connection

One of cool feature with OpenVPN is you could use multiple connection / configs with it. i.e. let's say you have 2 - 3 different config files for OpenVPN, you can configure GUI to use multiple connections for this.

Steps :

  1. Download and install latest OpenVPN GUI client  and TAP-for windows (https://openvpn.net/index.php/open-source/downloads.html): 
  2. With default installation GUI client will install one TAP interface for you, which should work for single connection at a time.
    1. For multiple VPN we need one tap device / connection
    2. "openvpn --show-adapters" will show current adapters list
    3. To add extra adapters use bat file "\Program Files\TAP-Windows\bin\addtap.bat"
  3. Now just Copy config files in "config" dir of openVPN, once you run openVPN GUI you will find all configs / connection available    


OpenVPN without username/password:

If you want to have password less login, then we can do that too.


  1. Create a file name cred.conf with username and password in each line
  2. Modify you existing config file and append "cred.conf" file name at end of  line "auth-user-pass login.config"

Deep Drive

Let's dig little deeper on what's VPN and what are these TAP devices for what they do ?


VPN:  It's a tunnel which allows your machine to connect to remote network.
            That's what we know but how does that work ?

          Will not go much deep in N/w but in short to go outside your n/w you will need to go via main gate of your network fence that's our Gateway. e.g. Let's say your address is in range 192.168.0.0/24, then you can fwd packages to others in your network 192.168.0.x directly, but for anything else will say will go via 192.168.0.1

             IPv4 Address. . . . . . . . . . . : 192.168.0.106
             Subnet Mask . . . . . . . . . . . : 255.255.255.0
             Default Gateway . . . . . . . . . : 192.168.0.1
          How to verify -- use traceroute or similar command.

         That's OK but how does this co-related to  VPN.

          We are getting there, So till now we are fine with our own n/w, Now let's say the earlier setting was of your home, now you brought you laptop to your office n/w and got different IP 10.10.x.x/18, bigger range, but still same will need one gateway.

         Now VPN helps you to bridge this gap i.e. from home network connect to your Office network. For that what they do is plug one extra network card (obviously virtual) and route traffic send via this card aka TAP device to your office external address which is pre-configured with VPN server to accept traffic with some authentication and connect to your office n/w


        Hence before connecting via VPN my "route --print 4" command will give output as :


        This interface 192.168.0.106 is physical.

        Now after connecting to VPN it's:

       We see that there is new interface 10.242.2.250 which is from our VPN.
         




   



Friday, June 20, 2014

My Lenovo E430 wifi issues



My Lenovo E430 Wi-Fi issues


                My Wi-Fi suddenly stopped working, Ok let’s admit it wasn’t sudden it was due to play I was doing with soft switch [Fn + F8], Essentially I was turning Wi-Fi on and off using soft switch that’s no sin.
                However My laptop doesn’t think that way, it failed to connect to Home Wi-Fi ,  I could not start it even performing on and off multiple times, Following are steps which I followed:
1.       Simple reboot – No luck
2.       Some post suggested to re-configure function keys using bios – No luck
3.       I was about to reinstalled Software / Drivers for Lenovo, Though to give chance to Windows Resolve N/w issue without any hope, but to my surprise it did job reported issue was “Soft Key Disabled Wi-Fi” which was known, however it did fix it and my WiFi is back.

Just hoping that someone do step no 3 first and ease pain, also have reduce soft switch uses.

Thursday, March 27, 2014

Creating Windows Image from ISO

Here are steps for creating windows image from ISO using virsh and qemu

1. Copy ISO to m/c
2. Create Disk file using qemu-img :
qemu-img create -f qcow2 -o preallocation=metadata windows_base_2012R2.qcow2 50G

3. Start VM using ISO:
virt-install --virt-type kvm --name windwos2012R2 --ram 2048 --cdrom=en_windows_server_2012_r2_x64_dvd_2707946.iso --disk windows_base_2012R2.qcow2,format=qcow2,cache=none --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole --os-type=windows


alternate command

virt-install --name windwos2012  --ram 2048 --cdrom /var/lib/libvirt/images/vm2/en_windows_server_2012_x64_dvd_915478.iso --disk /var/lib/libvirt/images/vm2/windows_base_2012.qcow2,bus=virtio,format=qcow2  --network  network=default,model=virtio --noautoconsole
4. use virt-manager to access GUI


Happy windows installation

Friday, March 7, 2014

Creating Bond on CentOS / RHEL

Hi,

Here are some steps to be followed to create bond on RHEL.

Little bit on bonding, It's giving two nic same IP / mac ID. benefit of this is two fold. 1st is failover i.e. for some reason if nic 1 / connection to nic 1 is broken nic 2 is at backup / standby. Another is LB this will not only balance load it will also gives more throughput which is necessary and good for connection having lot of trafic flow.

Process is pretty simple and similar to creation  of bridge, i.e. create another (virtual nic) and make actual nic slave of this virtual nic (Master), so that Apps will using Master nic for communication while OS will do actual work of deciding which nic to use, off-course doing this one way is half battle only to make full use of this feature it's also necessary that traffic will come to both nics and not only one, this could be achieved with managed switch which will do port bonding at switch level so traffic could be sent to both nics depening upon configuration.

1. Create virtual nic file :
           [root@controller1 ~]# cat /etc/sysconfig/network-scripts/ifcfg-bond1
           DEVICE=bond1
           IPADDR=172.29.25.10
           NETMASK=255.255.252.0
           ONBOOT=yes
           BOOTPROTO=none
           USERCTL=no
           NM_CONTROLLED=no
           BONDING_OPTS="mode=6"
      Point not is Bonding Options depending on OS they might differ but best to use is mode six i.e. balance-alb which will allow lb from both ends.

2. Next step is to remove all ip related data from actual nic and then add info about Bond and put them in slave, Pls note there is no physical nic master in this case master is virtual nic i.e. Bond.
       [root@controller1 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth2
DEVICE=eth2
HWADDR=00:1E:67:9A:B8:4F
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=none
MASTER=bond1
USERCTL=no
SLAVE=yes
USERCTL=no


Now do service network restart.

check with ifconfig only bond should get ip and other nic will be in slave mode