text:
# Как начинать разрабатывать на .NET?

На этой странице мы будем собирать информацию, полезную для новичков (как в программировании, так и в .NET). Наша цель — собрать здесь лучшие материалы, которые помогут понять:

- Основы программирования
- Базовые возможности .NET и C#
- Пути для дальнейшего развития

А еще мы записывали [вводную лекцию](https://www.youtube.com/watch?v=HV3n9NknQQc) о том, почему стоит изучать именно .NET, с чего проще начать и как не запутаться по пути.

## Основы программирования

С чего начинать вливаться в разработку, когда вы еще не знаете даже базовых терминов и понятий?

**[Курс "Основы программирования" на Ulearn](https://ulearn.me/course/basicprogramming/)**

Максимально полный курс по основам программирования, который рассказывает об основных понятиях как в программировании, как и в C#. В нем есть:

- Видеолекции с подробным разбором всех базовых понятий программирования, в том числе основ ООП.
- Небольшие тесты для проверки теоретических знаний.
- Задания на написание кода с автотестами.

Из возможных недостатков — кое-где это может оказаться занудным и для кого-то слишком "академическим". Однако на текущий момент это лучший открытый курс по основам программирования с примерами на C#, который можно найти на русском языке.

**Harvard CS50: Гарвардский курс по основам программирования — [плейлист на английском 2020 года](https://www.youtube.com/playlist?list=PLhQjrBD2T382_R182iC2gNZI9HzWFMC_8), [плейлист на русском 2015 года](https://www.youtube.com/playlist?list=PLawfWYMUziZqyUL5QDLVbe3j5BKWj42E5)**

Вероятно, лучший в мире курс по основам программирования. Великолепная подача, топовая экспертиза, актуальность (Гарвард выкладывает обновленную версию каждый год) и так далее. И вообще, это же практически возможность учиться программированию в Гарварде!

Чего может не хватать:

- Связи с C# и .NET.
- Практики написания кода и каких-то заданий.

Советую экспериментировать и пробовать применять все, о чем рассказывает лектор, в C#. Получите сразу двойную пользу — и материал закрепите, и разберетесь, как что-то работает в C#.

**[Курс по основам программирования от Николая Чернобаева и loftblog](https://www.youtube.com/playlist?list=PLY4rE9dstrJwoVF-svoIBhKzE-Ok39Zg_)**

Очень привлекательный своей простотой и наглядностью курс. Альтернатива двум прошлым, если вам не нравится лектор, стиль подачи или еще почему-то не зашло. Подано живо, корректно и в целом помогает влиться.

Недостатки те же, что и у Harvard CS50. Соответственно — также стоит пытаться повторять все показанное на C#, а лучше еще и как-то экспериментировать.

*А почему здесь только видеокурсы, без книг и статей?*

На текущий момент мне не удалось найти достаточно полных, интересных и мотивирующих текстовых курсов. Если кто-то предложит альтернативные варианты — обсудим и возможно добавим.

## Основы .NET и C#

**[Курс "Основы программирования" на Ulearn](https://ulearn.me/course/basicprogramming/) и его [вторая часть](https://ulearn.me/Course/BasicProgramming2)**

Собственно, именно поэтому Ulearn упомянут в этом списке первый — он хорош как для обучения основным понятиям программирования, так и для понимания основных возможностей C#.

Если вы выбирали именно его для обучения основам программирования — отлично, вероятно, вы уже разобрались с основными возможностями C#. А вторая часть курса рассказывает о более сложном функционале, вроде делегатов, дженериков и прочего.

**[Руководство по C# 9 и .NET 5 на Metanit](https://metanit.com/sharp/tutorial/)**

Хорошее, фундаментальное и детальное руководство по .NET и C#. Разбирает фактически все основные возможности C#. Из недостатков не самая легкая подача и временами неочевидные для новичка термины — можно легко запутаться.

Другой недостаток — это именно руководство, не курс. Здесь нет заданий для самопроверки или какой-то мотивации. Однако это руководство отлично работает как справочное пособие.

**[C# Tutorial от W3School](https://www.w3schools.com/cs/index.php)**

Простой и понятный туториал по C# от W3School. Не так глубоко погружается, не разбирает некоторые важные темы, но хорош, чтобы быстро по нему пройтись и разобраться с основами (особенно если вы базово знаете какой-нибудь другой язык).

Из плюсов — включает в себя много практических заданий и примеров кода, все примеры простые и очень детально разобраны.

Из минусов — не слишком глубоко копает, доступен только на английском.

**[Курсы для начинающих от Microsoft](https://docs.microsoft.com/ru-ru/learn/)**

Портал с курсами от Microsoft. Он достаточно удобен для тех, кто стартует с нуля — все очень дружелюбно, понятно, с кучей примеров кода, которые можно запускать прямо в браузере и всячески с ними экспериментировать.

Плюсы те же. Много практики, максимально просто и наглядно, всегда актуально (Microsoft часто обновляет контент).

Минусы — аналогично. Не все переведено на русский, частенько перевод кривой, глубоко эти курсы также не копают. Но хороши, чтобы в комфортной обстановке разбираться с возможностями языка, без погружения в детали.

**Книга "Язык программирования C# и платформа .NET" от Троелсена и Джепикса ([русская версия](https://www.ozon.ru/product/yazyk-programmirovaniya-c-7-i-platformy-net-i-net-core-146756705/?sh=qGR_5FxL), [более актуальная англоязычная версия](https://link.springer.com/book/10.1007/978-1-4842-6939-8))**

Классическая книга о C# от Эндрю Троелсена и Филиппа Джепикса. В отличие от многих книг о .NET, эта постоянно обновляется и выпускает новые обновления при выходе очередной версии .NET, что делает даже ее русскоязычное издание сравнительно актуальным.

Из плюсов — вероятно, это самый доскональный и детальный источник, не считая документации. Книга действительно огромная и разбирает огромное количество разнообразных аспектов. Минусы вытекают из плюсов, учиться с нуля по этой книге может быть очень сложно. Многие детали избыточны, а пояснения зачастую сложны для новичков в программировании.

В результате, эта книга является хорошим справочником, который может помочь в обучении по курсам или любому другому источнику. Для того, чтобы вам было проще к ней обращаться, мы положили под спойлер обзор полезных для новичка глав этой книги.

<details>
  <summary>Обзор глав</summary>

**Глава 3: базовые конструкции программирования на C#**

Основная информация, которую нужно извлечь, это работа с управляющими конструкциями (циклами и условиями), а также разные полезности о работе с консолью и строками.

При этом многое может показаться на этом этапе непонятным (к примеру, разбор класса System.Environment), подобное можно игнорировать. Основная цель этой главы — познакомиться с базовыми понятиями.

**Глава 4: работа с данными и методы в C#**

Здесь рассказывается о другой части базовых конструкций языка — массивах, типах и методах. Основная задача этой главы — объяснить, как можно группировать данные и логику.

Стоит отметить, что логически к концепциям этой главы относятся классы (о них можно прочитать в главах 5 и 6) и коллекции (о них рассказывается в главе 9). Классы куда чаще структур используются для группировки данных и логики, а коллекции куда чаще массивов для сбора одинаковых данных.

**Главы 5-8: объектно-ориентированное программирование на C#**

Здесь рассказывается о том, как реализовывать основные концепции из ООП в C#. Важное уточнение: эти главы и книга в целом не слишком детально раскрывают ООП как концепцию. Здесь рассказывается в основном о том, как пользоваться механизмами ООП в C#. Так что если вы еще не знаете концепции ООП, эти главы вам может быть непонятна.

**Главы 9-12: расширенные возможности C#**

Эти главы рассказывают о коллекциях и более специфичных для C# концепциях, таких как делегаты, события, лямбды, перегрузка операторов и LINQ. Это основные концепции, о которых вам стоит узнать из этих глав.

Опять же, кое-что может быть избыточно — например, информация об указателях и unsafe, этим вам на начальном этапе пользоваться точно не придется.

**Что еще может быть полезно?**

В четвертой части книги рассказывается о разнообразных библиотеках и фреймворках .NET. В частности, в главах 21 и 22 рассказывают об инструментах работы с базами данных,

Также интересны главы 29, 30 и 31. Они рассказывают об ASP.NET, фреймворке для разработки веб-приложений на .NET. В русскоязычном (более старом) издании глава 31 отдельно фокусируется на .NET Core, современной кроссплатформенной версии .NET, однако начиная с .NET 5 она слилась с .NET и является стандартом, а потому в новых версиях книги все главы фокусируются именно на кроссплатформенной версии .NET.
</details>

Приведенный в русской версии код примеров можно найти [на сайте издательства](http://www.williamspublishing.com/books/978-5-6040723-1-8.html) — его можно скачать и разбирать/редактировать в IDE.

**Итого**: ни один из этих источников, вероятно, не окажется полным и достаточным. Советую взять самый понятный и удобный для вас и комбинировать его с Metanit и гуглением. Главное не ударяйтесь в детали слишком сильно, ваша цель — понять, как писать простые программы на C#.

## А что дальше?

А этот раздел в доработке. Дальше здесь появятся ссылки на:

- Задачи на практику с автотестами (issue #17)
- Введение в веб-разработку
- Введение в базы данных
- Введение в ООП

Аналогично будут появляться ссылки на базовые страницы других блоков. Например, на основы desktop разработки.


text:
## Linux Tutorial
This tutorial is about Linux knowledge. It is intended for personal use only.

### Summary
1. [Basic Commands](./content/basic_commands.md)
2. [Working with files](./content/working_with_files.md)
3. [File System](./content/filesytem.md)
4. [File Permissions](./content/file_permissions.md)
5. [Package Management](./content/package_management.md)
6. [Data Backup](./content/data_backup.md)
7. [System Info](./content/system_info.md)
8. [Swap Memory](./content/swap_memory.md)
9. [User Envinronment](./content/user_env.md)
10. [Processes](./content/processes.md)
11. [Volume Manager Basics](./content/volume_manager.md)
12. [Advanced Volume Manager](./content/volume_manager_cont.md)
12. [Networking](./content/basic_networking.md)
13. [Network File System](./content/nfs.md)
14. [iSCSI](./content/shared_storage_iscsi.md)
15. [Security](./content/basic_security.md)
16. [Command Line](./content/command_line_prompt.md)
17. [Text Commands](./content/text_commands.md)
18. [Bash Programming](./content/bash_programming.md)
19. [Systemd](./content/systemd.md)
20. [Samba Server](./content/samba_server.md)
21. [Virtual Networking](./content/virtual-networking.md)
22. [Network Namespaces](./content/network-namespaces.md)
23. [Clustering Basics](./content/cluster-basics.md)
24. [Advanced Clustering](./content/cluster-adv.md)

repo_name: MinhKMA/Linux-Tutorial

mime_type: text/plain


text:
## Text commands
Linux provides utilities for file and text manipulation:

1. Display contents using ``cat`` and ``echo``.
2. Edit file contents using ``sed`` and ``awk``.
3. Search for patterns using ``grep``.

### Display contents
The ``cat`` is short for concatenate and is often used to read and print files as well as for simply viewing file contents, while the ``tac`` command prints the lines of a file in reverse order.
```
$ cat > myfile.txt
Mario Rossi
Antonio Esposito
Michele Laforca
Ctrl-D
$ cat myfile.txt
Mario Rossi
Antonio Esposito
Michele Laforca
$
$ tac myfile.txt
Michele Laforca
Antonio Esposito
Mario Rossi
```
The ``echo`` simply displays text.
```
$ echo myfile.txt
myfile.txt
]$echo HOME
HOME
$ echo $HOME
/home/ec2-user
```
### Edit file content
The command ``sed`` is a powerful text processing tool. Its name is an abbreviation for stream editor. It filters text as well as perform substitutions in data streams. Data from an input source/file (or stream) is taken and moved to a working space. The entire list of operations/modifications is applied over the data in the working space and the final contents are moved to the standard output space (or stream).
```
$ sed s/Mario/Saverio/ myfile.txt
Saverio Rossi
Antonio Esposito
Michele Laforca
$ cat myfile.txt
Mario Rossi
Antonio Esposito
Michele Laforca
$ sed s/Mario/Saverio/ myfile.txt >  myfile2.txt
$ cat myfile2.txt
Saverio Rossi
Antonio Esposito
Michele Laforca
$ sed -i s/Mario/Saverio/ myfile.txt
$ cat myfile.txt
Saverio Rossi
Antonio Esposito
Michele Laforca
```
For example, to convert 01/02/… to JAN/FEB/…
```
sed -e 's/01/JAN/' -e 's/02/FEB/' -e 's/03/MAR/' -e 's/04/APR/' -e 's/05/MAY/' \
-e 's/06/JUN/' -e 's/07/JUL/' -e 's/08/AUG/' -e 's/09/SEP/' -e 's/10/OCT/' \
-e 's/11/NOV/' -e 's/12/DEC/'
```
The ``awk`` command is used to extract and then print specific contents of a file and is often used to construct reports. It is a powerful utility and interpreted programming language, used to manipulate data files, retrieving, and processing text.
It works well with fields (containing a single piece of data, essentially a column) and records (a collection of fields, essentially a line in a file).

```
$ awk '{ print $0 }' myfile.txt
Saverio Rossi
Antonio Esposito
Michele Laforca
$ awk '{ print $1 }' myfile.txt
Saverio
Antonio
Michele
$ awk '{ print $2 }' myfile.txt
Rossi
Esposito
Laforca
```
Please, check the man pages for the ``awk`` and ``sed`` commands for futher details.

### File manipulation
The ``sort`` command is used to rearrange the lines of a text file either in ascending or descending order, according to a sort key.
```
# cat myfile.txt
Mario Rossi
Antonio Esposito
Michele Laforca
# sort myfile.txt
Antonio Esposito
Mario Rossi
Michele Laforca
# sort -r myfile.txt
Michele Laforca
Mario Rossi
Antonio Esposito
```
The ``uniq`` is used to remove duplicate lines in a text file and is useful for simplifying text display. It requires that the duplicate entries to be removed are consecutive.

```
# cat myfile.txt
Mario Rossi
Antonio Esposito
Michele Laforca
Antonio Esposito
# sort myfile.txt | uniq
Antonio Esposito
Mario Rossi
Michele Laforca
# sort myfile.txt | uniq -c
      2 Antonio Esposito
      1 Mario Rossi
      1 Michele Laforca
```

The ``paste`` command is used to combine fields from different files

```
# cat names.txt
Mario Rossi
Antonio Esposito
Michele Laforca
Antonio Esposito
[root@caldera01 ~]# cat ages.txt
34
46
29
46
[root@caldera01 ~]# paste names.txt ages.txt
Mario Rossi     34
Antonio Esposito        46
Michele Laforca 29
Antonio Esposito        46
```

The ``join`` command combines two files on a common field

```
# cat names.txt
01 Mario Rossi
02 Antonio Esposito
03 Michele Laforca
04 Antonio Esposito
# cat ages.txt
01 34
02 46
03 29
04 46
# join names.txt ages.txt
01 Mario Rossi 34
02 Antonio Esposito 46
03 Michele Laforca 29
04 Antonio Esposito 46
```

The ``grep`` comand is extensively used as a primary text searching tool. It scans files for specified patterns and can be used with regular expressions.
```
# grep Ant* names.txt
02 Antonio Esposito
04 Antonio Esposito
```
The ``tr`` utility is used to **tr**anslate specified characters into other characters or to delete them.
```
# cat names.txt
01 Mario Rossi
02 Antonio Esposito
03 Michele Laforca
04 Antonio Esposito
# cat names.txt | tr a-z A-Z
01 MARIO ROSSI
02 ANTONIO ESPOSITO
03 MICHELE LAFORCA
04 ANTONIO ESPOSITO
```
The ``tee`` command takes the output from any command, and while sending it to standard output, it also saves it to a file.
```
# ls -l | tee list.txt
total 32
-rw-r--r--. 1 root root   24 Mar  3 14:42 ages.txt
-rw-------. 1 root root 1883 Jan 21 20:53 anaconda-ks.cfg
-rw-r--r--. 1 root root   74 Mar  3 14:42 names.txt
-rwxr--r--. 1 root root  102 Feb 21 16:47 script.sh
-rw-r--r--. 1 root root   74 Mar  3 14:52 tr
[root@caldera01 ~]# cat list.txt
total 32
-rw-r--r--. 1 root root   24 Mar  3 14:42 ages.txt
-rw-------. 1 root root 1883 Jan 21 20:53 anaconda-ks.cfg
-rw-r--r--. 1 root root   74 Mar  3 14:42 names.txt
-rwxr--r--. 1 root root  102 Feb 21 16:47 script.sh
-rw-r--r--. 1 root root   74 Mar  3 14:52 tr
```

The ``wc`` (word count) counts the number of lines, words, and characters in a file or list of files.
```
# cat names.txt
01 Mario Rossi
02 Antonio Esposito
03 Michele Laforca
04 Antonio Esposito
[root@caldera01 ~]# wc -l names.txt
4 names.txt
[root@caldera01 ~]# wc -c names.txt
74 names.txt
[root@caldera01 ~]# wc -w names.txt
12 names.txt
```
The ``cut`` command is used for manipulating column-based files and is designed to extract specific columns. The default column separator is the tab character. A different delimiter can be given as a command option.
```
# cut -d" " -f1 names.txt
01
02
03
04
# cut -d" " -f2 names.txt
Mario
Antonio
Michele
Antonio
# cut -d" " -f3 names.txt
Rossi
Esposito
Laforca
Esposito
```

The ``head`` reads the first few lines of each named file (10 by default) and displays it on standard output.
```
# head -n 2 names.txt
01 Mario Rossi
02 Antonio Esposito
```
The ``tail`` prints the last few lines of each named file and displays it on standard output. By default, it displays the last 10 lines.
```
# tail -n 2 names.txt
03 Michele Laforca
04 Antonio Esposito
#
# tail -f -n3 /var/log/messages
Mar  3 14:38:59 caldera01 systemd: Started Session 35 of user root.
Mar  3 15:01:01 caldera01 systemd: Starting Session 36 of user root.
Mar  3 15:01:01 caldera01 systemd: Started Session 36 of user root.
```


text:
### Package Management Systems
The core parts of a Linux distribution and most of its add-on software are installed via the Package Management System. Each package contains the files and other instructions needed to make one software component work on the system. Packages can depend on each other. There are two broad families of package managers: those based on **dpkg** and those which use **rpm** as their low-level package manager. The two systems are incompatible, but provide the same features at a broad level.

**Package Management Systems**

|High Level Tool|Low Level Tool|Family|
|---------------|--------------|------|
|apt-get|dpkg|Debian|
|zypper|rpm|SUSE|
|yum|rpm|Red Hat|

Both package management systems provide two tool levels: a low-level tool (such as ``dpkg`` or ``rpm``), takes care of the details of unpacking individual packages, running scripts, getting the software installed correctly, while a high-level tool (such as ``apt-get``, ``yum``, or ``zypper``) works with groups of packages, downloads packages from the vendor, and figures out dependencies. Most of the time users need work only with the high-level tool, which will take care of calling the low-level tool as needed. Dependency tracking is a particularly important feature of the high-level tool, as it handles the details of finding and installing each dependency for you. Be careful, however, as installing a single package could result in many dozens or even hundreds of dependent packages being installed.

|Operation|RPM|Debian|
|---------|-----------|-----------|
|Install a package|rpm –i foo.rpm|dpkg --install foo.deb|
|Install a package with dependencies from repository|yum install foo|apt-get install foo|
|Remove a package|rpm –e foo.rpm|dpkg --remove foo.deb|
|Remove a package and dependencies using repository|yum remove foo|apt-get remove foo|
|Update package to a newer version|rpm –U foo.rpm|dpkg --install foo.deb|
|Update package using repository and resolving dependencies|yum update foo|apt-get upgrade foo|
|Update entire system|yum update|apt-get dist-upgrade|
|Show all installed packages|yum list installed|dpkg --list|
|Get information about an installed package including files|rpm –qil foo|dpkg --listfiles foo|
|Show available package with "foo" in name|yum list foo|apt-cache search foo|
|Show all available packages|yum list|apt-cache dumpavail|
|Show packages a file belong to|rpm –qf file|dpkg --search file|


text:
### Locating Applications
Depending on the specific distribution, programs and software packages can be installed in various directories. In general, executable programs should live in the following directories

```
/bin
/usr/bin
/sbin
/usr/sbin
/opt.
```

One way to locate programs is to employ the ``which`` utility. For example, to find out exactly where the diff program resides on the filesystem:
```
$ which diff
/usr/bin/diff
```
If which does not find the program, whereis is a good alternative because it looks for packages in a broader range of system directories:
```
$ whereis diff
diff: /usr/bin/diff /usr/share/man/man1/diff.1.gz
```
### Accessing Directories
The following commands are useful for directory navigation:

|Command|Result|
|-------|-----------|
|cd 	|Change to your home directory|
|cd ..|Change to parent directory|
|cd - |Change to previous directory|
|cd /	|Changes your current directory to the root (/) directory|

### Exploring the Filesystem
The tree command is a good way to get a bird’s-eye view of the filesystem tree. The following commands can help in exploring the filesystem:

|Command|Result|
|-------|-----------|
|ls 	  |List the contents of the present working directory|
|ls –a  |List all files including hidden files and directories|
|tree   |Displays a tree view of the filesystem|
|tree -d|Just list the directories and suppress listing file names|

### Hard and Symbolic Links
The ``ln`` command can be used to create hard links and or soft links, also known as symbolic links or symlinks. These two kinds of links are very common in UNIX-based operating systems.

Suppose that file1.txt already exists. A hard link, called file2.txt, is created with the command:
```
# ln file1.txt file2.txt
```
Note that two files now appear to exist. However, a closer inspection of the file listing shows that this is not quite true.

```
# ls -l file*
-rw-r--r--. 2 root root 604 Feb 16 11:49 file1.txt
-rw-r--r--. 2 root root 604 Feb 16 11:49 file2.txt
# ls -li file*
134415251 -rw-r--r--. 2 root root 604 Feb 16 11:49 file1.txt
134415251 -rw-r--r--. 2 root root 604 Feb 16 11:49 file2.txt
```
The -i option prints out in the first column the i-node number, which is a unique quantity for each file object. This field is the same for both of the two files; what is really going on here is that it is only one file but it has more than one name associated with it,  as is indicated by the 2 that appears in the output.

```
# ln file1.txt file3.txt
# ls -li file*
134415251 -rw-r--r--. 3 root root 604 Feb 16 11:49 file1.txt
134415251 -rw-r--r--. 3 root root 604 Feb 16 11:49 file2.txt
134415251 -rw-r--r--. 3 root root 604 Feb 16 11:49 file3.txt
```
Changing the file3.txt means change the same object as named as file1.txt, file2.txt and file3.txt.

Symbolic or Soft links are created with the -s option as in:

```
# ln -s file1.txt file4.txt
# ls -li file*
134415251 -rw-r--r--. 3 root root 644 Feb 16 11:59 file1.txt
134415251 -rw-r--r--. 3 root root 644 Feb 16 11:59 file2.txt
134415251 -rw-r--r--. 3 root root 644 Feb 16 11:59 file3.txt
134415252 lrwxrwxrwx. 1 root root   9 Feb 16 11:59 file4.txt -> file1.txt
```
Notice file4.txt no longer appears to be a regular file, and it clearly points to file1 and has a different inode number. Symbolic links take no extra space on the filesystem. They are extremely convenient as they can easily be modified to point to different places. An easy way to create a shortcut from your home directory to long pathnames is to create a symbolic link.

Unlike hard links, soft links can point to objects even on different filesystems (or partitions) which may or may not be currently available or even exist. In the case where the link does not point to a currently available or existing object, you obtain a dangling link.

Hard links are very useful and they save space, but you have to be careful with their use, sometimes in subtle ways. For one thing if you remove either file1.txt or file2.txt in the example, the inode object will remain, which might be undesirable as it may lead to subtle errors later if you recreate a file of that name. If you edit one of the files, exactly what happens depends on your editor; most editors including vi and gedit will retain the link by default but it is possible that modifying one of the names may break the link and result in the creation of two objects.


text:
## Advanced Clustering
Linux Clastering includes many advanced techniques to cover all types of Cluster. In the section [Cluster Basics](https://github.com/kalise/Linux-Tutorial/blob/master/content/cluster-basics.md) we setup a simple Active/Standby cluster. In this section, we are going to extend our Cluster to become an Active/Active cluster.

In an Active/Standby cluster, the standby node is doing nothing for most of the time. Since we do not have shared data between the two nodes, there is no risk of data corruption. The second node can partecipate to the cluster task becoming an active member and improving the performances of the whole cluster. To achieve this goals, we make the HTTP Server running on both the nodes and installing a Load Balancer on both the nodes to distribute the client's requests in a Round Robin fashion.

![](../img/active-active-cluster.jpg?raw=true)

Remove the HTTP Server resource from the Cluster

    [root@benji ~]# pcs resource delete HTTPServer
    Attempting to stop: HTTPServer...Stopped

Add back the HTTP Server resource by changing its type

    [root@benji ~]# pcs resource create httpd systemd:httpd \
    > configfile=/etc/httpd/conf/httpd.conf \
    > op monitor interval=30s clone

We changed from ``ocf:heartbeat:apache`` to ``systemd:httpd`` since we want the HTTP Server started as Systemd daemon. This permits to have the server running on both the nodes at same time. Please, note that service is still managed by Pacemaker and it should not be started by Systemd.

On both the nodes, install the Load Balancer. We'll use HAProxy for simplicity

    [root@benji ~]# yum install haproxy -y

Make sure the same configuration file is present on both the nodes

    [root@benji ~]# vi /etc/haproxy/haproxy.cfg
    #---------------------------------------------------------------------
    # Global settings
    #---------------------------------------------------------------------
    global
        log         127.0.0.1 local2
        chroot      /var/lib/haproxy
        pidfile     /var/run/haproxy.pid
        maxconn     4000
        user        haproxy
        group       haproxy
        daemon
        # turn on stats unix socket
        stats socket /var/lib/haproxy/stats
    #---------------------------------------------------------------------
    # Common defaults
    #---------------------------------------------------------------------
    defaults
        mode                    http
        log                     global
        option                  httplog
        option                  dontlognull
        option http-server-close
        option forwardfor       except 127.0.0.0/8
        option                  redispatch
        retries                 3
        timeout http-request    10s
        timeout queue           1m
        timeout connect         10s
        timeout client          1m
        timeout server          1m
        timeout http-keep-alive 10s
        timeout check           10s
        maxconn                 3000
    #---------------------------------------------------------------------
    # Listen configuration
    #---------------------------------------------------------------------
    listen apache
        bind 10.10.10.23:80 transparent #bind to the Virtual IP
        mode http
        option http-server-close
        option forwardfor
        balance roundrobin
        server holly 10.10.10.22:80 check
        server benji 10.10.10.24:80 check

The HAProxy binds to the Virtual IP address and then forward the client's requests to the HTTP Servers in a Round Robin fashion. To avoid conflict binding between the HTTP Server and HAProxy, make sure the HTTP Servers listen only on the IP addresses. To achieve this, configure the ``/etc/httpd/conf/httpd.conf`` configuration file, by specifing the IP address:

    [root@benji ~]# vi /etc/httpd/conf/httpd.conf
    ...
    Listen 10.10.10.24:80
    ...
    [root@holly ~]# vi /etc/httpd/conf/httpd.conf
    ...
    Listen 10.10.10.22:80
    ...

Since we need the Load Balancer running on both the nodes to handle the client's requests, add the HAProxy resource to the Cluster as a Systemd daemon.

    [root@benji ~]# pcs resource create haproxy systemd:haproxy \
    > op monitor interval=15s clone

Restart the cluster

    [root@benji ~]# pcs cluster start --all
    holly: Starting Cluster...
    benji: Starting Cluster...

and check the status

    [root@benji ~]# pcs status
    Cluster name: mycluster
    Last updated: Mon Jul 18 01:06:01 2016
    Stack: corosync
    Current DC: holly.b-cloud.it (version 1.1.13-10.el7_2.2-44eb2dd) - partition with quorum
    2 nodes and 5 resources configured
    Online: [ benji holly ]
    Full list of resources:
        VIP-10.10.10.23        (ocf::heartbeat:IPaddr2):       Started benji
        Clone Set: httpd-clone [httpd]
             Started: [ benji holly ]
        Clone Set: haproxy-clone [haproxy]
             Started: [ benji holly ]
        PCSD Status:
          holly: Online
          benji: Online
        Daemon Status:
          corosync: active/enabled
          pacemaker: active/enabled
          pcsd: active/enabled

The Cluster is running with the Virtual IP on the **Benji** node

    [root@benji ~]#  netstat -tupln | grep 80
    tcp        0      0 10.10.10.23:80          0.0.0.0:*               LISTEN      9251/haproxy
    tcp        0      0 10.10.10.24:80          0.0.0.0:*               LISTEN      1729/httpd
    [root@benji ~]# ip addr show ens32
    2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:20:d2:dd brd ff:ff:ff:ff:ff:ff
        inet 10.10.10.24/24 brd 10.10.10.255 scope global ens32
           valid_lft forever preferred_lft forever
        inet 10.10.10.23/32 brd 10.10.10.255 scope global ens32
           valid_lft forever preferred_lft forever

    [root@holly ~]# netstat -tupln | grep 80
    tcp        0      0 10.10.10.23:80          0.0.0.0:*               LISTEN      18467/haproxy
    tcp        0      0 10.10.10.22:80          0.0.0.0:*               LISTEN      18444/httpd
    udp6       0      0 fe80::20c:29ff:fe77:123 :::*                                623/ntpd
    [root@holly ~]#  ip addr show ens32
    2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:77:68:56 brd ff:ff:ff:ff:ff:ff
        inet 10.10.10.22/24 brd 10.10.10.255 scope global ens32
           valid_lft forever preferred_lft forever

Check the services are started in Systemd fashion

    [root@benji ~]# systemctl status haproxy
    ● haproxy.service - Cluster Controlled haproxy
       Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)
      Drop-In: /run/systemd/system/haproxy.service.d
               └─50-pacemaker.conf
       Active: active (running) since Mon 2016-07-18 01:05:55 CEST; 5min ago
     Main PID: 1748 (haproxy-systemd)
       CGroup: /system.slice/haproxy.service
               ├─1748 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
               ├─1749 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
               └─1750 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
    Jul 18 01:05:55 benji systemd[1]: Started Cluster Controlled haproxy.
    Jul 18 01:05:55 benji systemd[1]: Starting Cluster Controlled haproxy...

and

    [root@benji ~]# systemctl status httpd
    ● httpd.service - Cluster Controlled httpd
       Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
      Drop-In: /run/systemd/system/httpd.service.d
               └─50-pacemaker.conf
       Active: active (running) since Mon 2016-07-18 01:05:53 CEST; 6min ago
         Docs: man:httpd(8)
               man:apachectl(8)
     Main PID: 1729 (httpd)
       Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
       CGroup: /system.slice/httpd.service
               ├─1729 /usr/sbin/httpd -DFOREGROUND
               └─1734 /usr/sbin/httpd -DFOREGROUND
    Jul 18 01:05:52 benji systemd[1]: Starting Cluster Controlled httpd...
    Jul 18 01:05:53 benji systemd[1]: Started Cluster Controlled httpd.

Set that the order of starting is the Virtual IP first and then the other services. This is required to assure there is always an IP Address where to send client's requests. Also make sure that the Floating IP and the HAProxy are always working togheter.

    [root@benji ~]# pcs constraint order VIP-10.10.10.23 then haproxy-clone
    Adding VIP-10.10.10.23 haproxy-clone (kind: Mandatory) (Options: first-action=start then-action=start)
    [root@benji ~]# pcs constraint order httpd-clone then haproxy-clone
    Adding httpd-clone haproxy-clone (kind: Mandatory) (Options: first-action=start then-action=start)
    [root@benji ~]# pcs constraint colocation add VIP-10.10.10.23 with haproxy-clone
    [root@benji ~]# pcs constraint
    Location Constraints:
    Ordering Constraints:
      start VIP-10.10.10.23 then start haproxy-clone (kind:Mandatory)
      start httpd-clone then start haproxy-clone (kind:Mandatory)
    Colocation Constraints:
      VIP-10.10.10.23 with haproxy-clone (score:INFINITY)

We are redy to test the Cluster

    [stack@director ~]$ curl http://10.10.10.23
    Hello Holly
    [stack@director ~]$ curl http://10.10.10.23
    Hello Benji
    [stack@director ~]$ curl http://10.10.10.23
    Hello Holly


text:
### Linux swap memory
Linux divide la RAM in aree di memoria chiamate pagine. Lo **swapping** è il processo mediante il quale una pagina di memoria viene copiata in uno spazio preconfigurato sul disco rigido, chiamato spazio di **swap**, per liberare dalla memoria. Le dimensioni combinate della memoria fisica e dello spazio di swap è la quantità di memoria virtuale disponibile. Lo swapping è necessario per due motivi importanti:

1. In primo luogo, quando il sistema richiede più memoria di quella fisicamente disponibile, il kernel sposta le pagine meno utilizzate nello spazio di swap e concede l’utilizzo della memoria ram all’applicazione corrente (processo) che in quel momento richiede la memoria.
2. In secondo luogo, un numero significativo di pagine utilizzate da un’applicazione durante la sua fase di avvio possono essere utilizzate solo per l’inizializzazione del sistema e poi mai più usate.

Il sistema è in grado di usare quindi lo swap su quelle pagine e di liberare la memoria per altre applicazioni o addirittura per la cache su disco. Tuttavia, lo swapping ha un rovescio della medaglia. Rispetto alla memoria RAM, i dischi sono molto più lenti. La velocità della memoria è misurata in nanosecondi, mentre quella dei dischi in millisecondi, dunque l’accesso al disco è decine di migliaia di volte più lento rispetto alla memoria ram. Più operazioni di swapping che si verificano, più lento il vostro sistema sarà. A volte un eccessivo swapping crea dei colli di bottiglia, poichè si verifica una particolare situazione: una pagina viene messa nello swap e poi portata in ram molto velocemente ed in modo continuativo. In tali situazioni il sistema lotta per trovare della memoria libera e mantenere le diverse applicazioni in esecuzione nello stesso momento. In questo caso, solo l’aggiunta di RAM più aiutare la stabilità del sistema stesso.

Linux ha due forme di spazio di swap: la partizione di swap e il file di swap. La partizione di swap è una sezione indipendente del disco fisso, utilizzati esclusivamente per lo swap, nessun altro può risiedere lì. Il file di swap è un file speciale che risiede nel filesystem tra il sistema e file di dati. Per vedere com’è fatto e dove è ubicato lo spazio di swap che si possiede, si utilizza il comando ``swapon``.

```
# swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-0                               partition       4079612 0       -1
```

Ogni riga elenca una partizione di swap separata utilizzata dal sistema. Una particolarità dello swap su linux è che, se montare due (o più) spazi di swap (preferibilmente su due dispositivi differenti) con la stessa priorità, linux divide le sue attività di swapping tra di loro. Questo si traduce in un incremento notevole delle prestazioni. Per aggiungere una partizione di swap per il vostro sistema, è necessario però prima di prepararla.

### Add a swap area as a file
```
dd if=/dev/zero of=/var/swapfile bs=1M count=2048
chmod 600 /var/swapfile
mkswap /var/swapfile
echo /var/swapfile none swap defaults 0 0 | sudo tee -a /etc/fstab
swapon -a
```


text:
### Users and Groups
Linux is a multiuser operating system where more than one user can log on at the same time. The ``who`` command lists the currently logged-on users. To identify the current user, use the ``whoami`` command.

```
# who -a
           system boot  2015-02-17 13:28
LOGIN      tty1         2015-02-17 13:28               761 id=tty1
root     + pts/0        2015-02-17 13:29   .         12379 (10.10.10.246)
           run-level 3  2015-02-17 13:29
root     + pts/1        2015-02-17 17:37   .         18762 (10.10.10.246)
```
Linux uses groups for organizing users. Groups are collections of accounts with certain shared permissions. Control of group membership is administered through the ``/etc/group`` file, which shows a list of groups and their members. By default, every user belongs to a default or primary group. When a user logs in, the group membership is set for their primary group and all the members enjoy the same level of access and privilege. Permissions on various files and directories can be modified at the group level.

All Linux users are assigned a unique user ID, the **uid**, which is just an integer, as well as one or more group ID’s, the  **gid**, including a default one which is the same as the user ID. Historically, RedHat based distros start uid's at 500. Other distributions begin at 1000. These numbers are associated with names through the files ``/etc/passwd`` and ``/etc/group``. Groups are used to establish a set of users who have common interests for the purposes of access rights, privileges, and security considerations. Access rights to files and devices are granted on the basis of the user and the group they belong to.

Only the root user can add and remove users and groups. Adding a new user is done with the ``useradd`` command and removing an existing user is done with the ``userdel`` command. In the simplest form an account for the new user adriano would be done with:
```
# useradd adriano
# cat /etc/passwd | grep adriano
adriano:x:1000:1000::/home/adriano:/bin/bash
# ls -lrta /home/adriano/
total 16
-rw-r--r--. 1 adriano adriano 231 Sep 26 03:53 .bashrc
-rw-r--r--. 1 adriano adriano 193 Sep 26 03:53 .bash_profile
-rw-r--r--. 1 adriano adriano  18 Sep 26 03:53 .bash_logout
drwxr-xr-x. 3 root    root     20 Feb 17 17:48 ..
-rw-------. 1 adriano adriano   9 Feb 17 17:49 .bash_history
drwx------. 2 adriano adriano  79 Feb 17 17:49 .
```
which by default sets the his home directory to ``/home/adriano``, populates it with some basic files and sets the default shell to ``/bin/bash``.

Remove the user account by typing:
```
# userdel adriano
# cat /etc/passwd | grep adriano
# ls -lrta /home/adriano/
total 16
-rw-r--r--. 1 1000 1000 231 Sep 26 03:53 .bashrc
-rw-r--r--. 1 1000 1000 193 Sep 26 03:53 .bash_profile
-rw-r--r--. 1 1000 1000  18 Sep 26 03:53 .bash_logout
drwxr-xr-x. 3 root root  20 Feb 17 17:48 ..
-rw-------. 1 1000 1000   9 Feb 17 17:49 .bash_history
drwx------. 2 1000 1000  79 Feb 17 17:49 .
```
However, this will leave the home directory intact. This might be useful if it is a temporary inactivation. To remove the home directory while removing the account one needs to use the related option.
```
# userdel -r adriano
# cat /etc/passwd | grep adriano
# ls -lrta /home/adriano/
ls: cannot access /home/adriano/: No such file or directory
```
The command ``id`` with no argument gives information about the current user. If given the name of another user as an argument, id will report information about that other user.
```
# id
uid=0(root) gid=0(root) groups=0(root)
# id adriano
uid=1000(adriano) gid=1000(adriano) groups=1000(adriano)
```
Use the ``passwd`` command to change the password for the new user
```
# passwd adriano
Changing password for user adriano.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```

Adding a new group is done with the ``groupadd`` command and removed with the ``groupdel`` command.
```
# groupadd newgroup
# groupdel newgroup
```
Adding a user to an already existing group is done with the ``usermod`` command. Removing a user from the group is a somewhat trickier.

```
# groupadd newgroup
# usermod -G newgroup adriano
# groups adriano
adriano : adriano newgroup
# usermod -g newgroup adriano
# groups adriano
adriano : newgroup
#
```
All these commands update the ``/etc/group`` as necessary. The ``groupmod`` command can be used to change the group properties such as the Group ID or the name
```
# groupmod newgroup -n newgoupname
# groups adriano
adriano : newgoupname
```

### The root user
The **root** account is very powerful and has full access to the system. Other operating systems often call this the administrator account; in Linux it is often called the **superuser** account. You must be extremely cautious before granting full root access to a user; it is rarely if ever justified. External attacks often consist of tricks used to elevate to the root account. However, you can use the sudo feature to assign more limited privileges to standard user accounts:

1. on only a temporary basis.
2. only for a specific subset of commands.

When assigning elevated privileges, you can use the command ``su`` (switch user) to launch a new shell running as another user (you must type the password of the user you are becoming). Most often this other user is root, and the new shell allows the use of elevated privileges until it is exited. It is almost always a bad (dangerous for both security and stability) practice to use ``su`` to become root. Resulting errors can include deletion of vital files from the system and security breaches.

### Startup Files
In Linux, the command shell program, generally **bash** uses one or more startup files to configure the environment. Files in the ``/etc`` directory define global settings for all users while the initialization files in the user's home directory can include and or override the global settings. The startup files can do anything the user would like to do in every command shell, such as:

* Customizing the user's prompt
* Defining command-line shortcuts and aliases
* Setting the default text editor
* Setting the path for where to find executable programs

When you first login to Linux, the  ``/etc/profile`` file is read and evaluated, after which the following files are searched in the listed order:

1. ``~/.bash_profile``
2. ``~/.bash_login``
3. ``~/.profile``

The Linux login shell evaluates whatever startup file that it comes across first and ignores the rest. This means that if it finds ``~/.bash_profile``, it ignores the rest. Different distributions may use different startup files. However, every time you create a new shell, or terminal window, etc., you do not perform a full system login; only the ``~/.bashrc`` file is read and evaluated. Although this file is not read and evaluated along with the login shell, most distributions and/or users include the ``~/.bashrc`` file from within one of the three user-owned startup files. In the Ubuntu, openSuse, and CentOS distros, the user must make appropriate changes in the ``~/.bash_profile`` file to include the ``~/.bashrc`` file. The ``~/.bash_profile`` will have certain extra lines, which in turn will collect the required customization parameters from ``~/.bashrc``.

### Environment variables
The environment variables are simply named quantities that have specific values and are understood by the command shell, such as **bash**. Some of these are pre-set by the system, and others are set by the user either at the command line or within startup and other scripts. An environment variable is actually no more than a character string that contains information used by one or more applications. There are a number of ways to view the values of currently set environment variables. All the ``set``, ``env``, or ``export`` commands display the environment variables.

By default, variables created within a script are only available to the current shell. All the child processes (sub-shells) will not have access to values that have been set or modified. Allowing child processes to see the values, requires use of the ``export`` command.

|Task|Command|
|----|-------|
|Show the value of a specific variable|echo $SHELL|
|Export a new variable value|export VAR=value|
|Add a variable permanently|Add the line export VAR=value to ~/.bashrc|

The **HOME** is an environment variable that represents the home or login directory of the user. The ``cd`` command without arguments will change the current working directory to the value of HOME. Note the tilde character (~) is often used as an abbreviation for $HOME.

The **PATH** environment variable is an ordered list of directories which is scanned when a command is given to find the appropriate program or script to run. Each directory in the path is separated by colons. An empty directory name indicates the current directory at any given time.

```
$ export PATH=$HOME/bin:$PATH
$ echo $PATH
/home/me/bin:/usr/local/bin:/usr/bin:/bin/usr
```

The **PS** environment variable (Prompt Statement) is used to customize your prompt string in your terminal windows to display the information you want. PS1 is the primary prompt variable which controls what your command line prompt looks like. The following special characters can be included in PS1 :

|Character|Usage|
|---------|-----|
|\u|User name|
|\h|Host name|
|\w|Current working directory|
|\!|History number of this command|
|\d|Date|

They must be surrounded in single quotes when they are used
```
# export PS1='\u@\h:\w$ '
root@caldera01:~$
root@caldera01:~$ export PS1='\d-\u@\h:\w$ '
Wed Feb 18-root@caldera01:~$
```
The **SHELL** environment variable points to the user's default command shell (the program that is handling whatever you type in a command window, usually bash) and contains the full pathname to the shell
```
$ echo $SHELL
/bin/bash
$
```

### Command history
The bash keeps track of previously entered commands and statements in a history buffer; you can recall previously used commands simply by using the Up and Down cursor keys. To view the list of previously executed commands, you can use the ``history`` at the command line. The list of commands is displayed with the most recent command appearing last in the list. This information is stored in ``~/.bash_history`` file. Several associated environment variables can be used to get information about the history file.

|Variable|Usage|
|--------|-----|
|HISTFILE|stores the location of the history file|
|HISTFILESIZE|stores the maximum number of lines in the history file|
|HISTSIZE|stores the maximum number of lines in the history file for the current session|

The table below shows the syntax used to execute previously used commands

|Syntax|Usage|
|------|-----|
|!!|Execute the previous command|
|!|Start a history substitution|
|!$|Refer to the last argument in a line|
|!n|Refer to the n-th command line|
|!string|Refer to the most recent command starting with string|

### Creating Aliases
Customized commands can be created to modify the behavior of already existing ones by creating aliases. Most often these aliases are placed in your ``~/.bashrc`` file so they are available to any command shells you create. The ``alias`` command with no arguments will list currently defined aliases.

```
$ alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
```


text:
## Logical Volume Manager layout
Basically a Logical Volume Manager layout **LVM** looks like this:

* **Logical Volume(s)**: ``/dev/fileserver/share``, ``/dev/fileserver/backup``, ``/dev/fileserver/media``
* **Volume Group(s)**: ``fileserver``
* **Physical Volume(s)**: ``/dev/sdb1``, ``/dev/sdc1``, ``/dev/sdd1``, ``/dev/sdc1``

You have one or more physical volumes, and on these physical volumes you create one or more volume groups, and in each volume group you can create one or more logical volumes. If you use multiple physical volumes, each logical volume can be bigger than one of the underlying physical volumes (but of course the sum of the logical volumes cannot exceed the total space offered by the physical volumes). It is a good practice to not allocate the full space to logical volumes, but leave some space unused. That way you can enlarge one or more logical volumes later on if you feel the need for it.

With LVM, an hard drive or set of hard drives or different partitions of the same hard drive are allocated to one or more physical volumes. The physical volumes can be placed on other block devices which might span two or more disks. The physical volumes are combined into logical volumes, with the exception of the ``/boot`` partition. The ``/boot`` partition cannot be on a logical volume group because the boot loader cannot read it. If the root partition is on a logical volume, create a separate ``/boot`` partition which is not a part of a volume group. Since a physical volume cannot span over multiple drives, to span over more than one drive, create one or more physical volumes per drive.

The volume groups can be divided into logical volumes, which are assigned mount points, such as ``/home`` and root and file system types, such as **ext2** or **ext3**. When the partitions reach their full capacity, free space from the volume group can be added to the logical volume to increase the size of the partition. When a new hard drive is added to the system, it can be added to the volume group, and partitions that are logical volumes can be increased in size.

### Create a LVM layout
On my local CentOS machine, there is on additional hard drive ``/dev/sdb`` to use for LVM layout.
```
# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   8e  Linux LVM

Command (m for help):
```

The disk is already partitioned as Linux LVM, so no needs to do further. To create the LVM layout, first we need to create a physical volume
```
# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created
# pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sdb1       lvm2 ---  232.88g 232.88g
# pvscan
  PV
  /dev/sdb1           lvm2 [232.88 GiB]
  Total: 3 [465.28 GiB] / in use: 2 [232.39 GiB] / in no VG: 1 [232.88 GiB]
# pvdisplay
 "/dev/sdb1" is a new physical volume of "232.88 GiB"
  --- NEW Physical volume ---
  PV Name               /dev/sdb1
  VG Name
  PV Size               232.88 GiB
  Allocatable           NO
  PE Size               0
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               ajGCMg-Y4cG-v4AD-Wxma-TaE5-zQig-XmnYAx
```

Now create the volume group
```
# vgcreate storage /dev/sdb1
  Volume group "storage" successfully created
# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "storage" using metadata type lvm2
# vgs
  VG      #PV #LV #SN Attr   VSize   VFree
  storage   1   0   0 wz--n- 232.88g 232.88g
# vgdisplay
  --- Volume group ---
  VG Name               storage
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               232.88 GiB
  PE Size               4.00 MiB
  Total PE              59618
  Alloc PE / Size       0 / 0
  Free  PE / Size       59618 / 232.88 GiB
  VG UUID               nEcTxG-p5K6-npqD-OVeX-dRI1-aWP9-o4D1Z1

```
Now, everything is ready to create the logical volumes from the volume group
```
# lvcreate -L 20G -n db-area storage
  Logical volume "db-area" created.
# lvcreate -L 10G -n users-area storage
  Logical volume "users-area" created.
# lvcreate -L 60G -n staging-area storage
  Logical volume "staging-area" created.
# lvcreate -l 100%FREE -n spare storage
  Logical volume "spare" created.
# lvs
  LV           VG      Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  db-area      storage -wi-a-----  20.00g
  spare        storage -wi-a----- 142.88g
  staging-area storage -wi-a-----  60.00g
  users-area   storage -wi-a-----  10.00g
# lvscan
  ACTIVE            '/dev/storage/db-area' [20.00 GiB] inherit
  ACTIVE            '/dev/storage/users-area' [10.00 GiB] inherit
  ACTIVE            '/dev/storage/staging-area' [60.00 GiB] inherit
  ACTIVE            '/dev/storage/spare' [142.88 GiB] inherit
```
After creating the appropriate filesystem on the logical volumes, they become ready to use for the storage purpose
```
# mkfs.ext4 /dev/storage/db-area
# mkfs.ext4 /dev/storage/users-area
# mkfs.ext4 /dev/storage/staging-area
# mkfs.ext4 /dev/storage/spare

# mkdir /db
# mount /dev/storage/db-area /db
# mkdir /users
# mount /dev/storage/users-area /users
# mkdir /staging
# mount /dev/storage/staging-area /staging

```

### Extend a LVM layout
On the local CentOS machine, there are 2 hard drive ``/dev/sda`` and ``/dev/sdb``. The ``/dev/sda`` is partioned as follow
```
# fdisk -l /dev/sda

Disk /dev/sda: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000b78bc

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1026047      512000   83  Linux
/dev/sda2         1026048   155004927    76989440   8e  Linux LVM
/dev/sda3       155004928   488397167   166696120   83  Linux LVM
```

The ``/dev/sda1`` is for the ``/boot`` partition and is not into LVM layout. Both ``/dev/sda2`` and ``/dev/sda3`` partitions are part of the LVM layout. Note that both the partitions are part of the same physical disk. This is not so common in production but is possible to have. More common is the case of partitions belonging to different physical disks.
```
# lvmdiskscan
  /dev/os/swap [       3.89 GiB]
  /dev/sda1    [     500.00 MiB]
  /dev/os/root [      50.00 GiB]
  /dev/sda2    [      73.42 GiB] LVM physical volume
  /dev/os/data [     178.50 GiB]
  /dev/sda3    [     158.97 GiB] LVM physical volume
  /dev/sdb1    [     232.88 GiB]
  3 disks
  2 partitions
  0 LVM physical volume whole disks
  2 LVM physical volumes

# pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda2  os   lvm2 a--   73.42g    0
  /dev/sda3  os   lvm2 a--  158.97g    0

# vgs
  VG   #PV #LV #SN Attr   VSize   VFree
  os     2   3   0 wz--n- 232.39g    0

# lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  data os   -wi-ao---- 178.50g
  root os   -wi-ao----  50.00g
  swap os   -wi-ao----   3.89g
```
The two partitons are seen as two LVM physical volumes: ``/dev/sda2`` and ``/dev/sda3``. The two phisical volumes are part of the same volume group called ``os``. On top of this volume group there are three logical volumes: ``/root``, ``/data`` and ``/swap``.

We want to increase the space of the LVM layout with a new partition belonging to the second hard drive ``/dev/sdb``. The hard drive is partitioned as follow:
```
# fdisk -l /dev/sdb

Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   83  Linux

```

The partition ``/dev/sdb1`` is Linux type. Change the partition type to Linux LVM
```
# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p

Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   83  Linux

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

Command (m for help): p

Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   8e  Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
```
A warning message which basically means in order to use the new table with the changes a system reboot is required. As workaround, run the ``partprobe -s`` to rescan the partitions.

```
# partprobe -s
/dev/sda: msdos partitions 1 2 3
/dev/sdb: msdos partitions 1
```

Create a new physical volume from the new partition
```
# pvcreate /dev/sdb1
WARNING: xfs signature detected on /dev/sdb1 at offset 0. Wipe it? [y/n] y
  Wiping xfs signature on /dev/sdb1.
  Physical volume "/dev/sdb1" successfully created
```

Check the new physical volume just created by ``pvdisplay`` command
```
# pvdisplay
   "/dev/sdb1" is a new physical volume of "232.88 GiB"
  --- NEW Physical volume ---
  PV Name               /dev/sdb1
  VG Name
  PV Size               232.88 GiB
  Allocatable           NO
  PE Size               0
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               qtRwhD-Pxcv-JQlD-u7xu-lNi0-CiBv-F9XUoO
```

Now extend the ``os`` volume group by adding in the new physical volume which we created earlier
```
# vgextend os /dev/sdb1
  Volume group "os" successfully extended
```

Using the ``pvscan`` command we scan all disks for physical volumes, this should confirm the new created physical volume ``/dev/sdb1`` and along with the old volumes
```
# pvscan
  PV /dev/sda2   VG os   lvm2 [73.42 GiB / 0    free]
  PV /dev/sda3   VG os   lvm2 [158.97 GiB / 0    free]
  PV /dev/sdb1   VG os   lvm2 [232.88 GiB / 232.88 GiB free]
  Total: 3 [465.28 GiB] / in use: 3 [465.28 GiB] / in no VG: 0 [0   ]
```

Next want to increase the logical volume ``/dev/os/data`` which basically means we will be taking our original logical volume ``/dev/os/data`` and extending it over the new physical volume ``/dev/sdb1`` just created.

```
# lvscan
  ACTIVE            '/dev/os/root' [50.00 GiB] inherit
  ACTIVE            '/dev/os/swap' [3.89 GiB] inherit
  ACTIVE            '/dev/os/data' [178.50 GiB] inherit
# lvextend /dev/os/data /dev/sdb1
  Extending logical volume data to 411.39 GiB
  Logical volume data successfully resized
# lvscan
  ACTIVE            '/dev/os/root' [50.00 GiB] inherit
  ACTIVE            '/dev/os/swap' [3.89 GiB] inherit
  ACTIVE            '/dev/os/data' [411.39 GiB] inherit
```

Note the size of the logical volume ``/dev/os/data`` increased from 178.50 GiB to 411.39 GiB. Howewer, the size of the ``/data`` file system is still 179G
```
# df -h
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/os-root   50G  2.0G   48G   4% /
devtmpfs             1.8G     0  1.8G   0% /dev
tmpfs                1.9G     0  1.9G   0% /dev/shm
tmpfs                1.9G  8.6M  1.8G   1% /run
tmpfs                1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mapper/os-data  179G   33M  179G   1% /data
/dev/sda1            497M  183M  315M  37% /boot
```

There is then one final step which is to resize the file system so that it can take advantage of this additional space, this is done using the ``resize2fs`` command. In our case, the command will fail since we are using *xfs* file system. We need to use the ``xfs_growfs`` to have the same effect.
```
# xfs_growfs /dev/os/data
meta-data=/dev/mapper/os-data    isize=256    agcount=4, agsize=11698432 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=46793728, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=22848, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 46793728 to 107842560

# df -h
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/os-root   50G  2.0G   48G   4% /
devtmpfs             1.8G     0  1.8G   0% /dev
tmpfs                1.9G     0  1.9G   0% /dev/shm
tmpfs                1.9G  8.6M  1.8G   1% /run
tmpfs                1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mapper/os-data  412G   33M  412G   1% /data
/dev/sda1            497M  183M  315M  37% /boot
```

### Reduce the LVM layout
Unfortunally we can NOT make a XFS partition smaller online. The only way to shrink is to do a complete dump of data, make a new smaller volume group and restore the data.

```
# mkdir /dump
# mv /data/* /dump/
# umount /data
```

Remove the logical volume ``/dev/os/data``
```
# lvremove /dev/os/data
Do you really want to remove active logical volume data? [y/n]: y
  Logical volume "data" successfully removed
# lvscan
  ACTIVE            '/dev/os/root' [50.00 GiB] inherit
  ACTIVE            '/dev/os/swap' [3.89 GiB] inherit
```
Detouch the physical volume from the volume group. To accomplish this task, use the ``vgreduce`` command. This command shrinks a volume group's capacity by removing one or more physical volumes. This frees the physical volumes to be used in other volume groups or to be removed from the system.

```
# vgreduce os /dev/sdb1
  Removed "/dev/sdb1" from volume group "os"
# pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda2  os   lvm2 a--   73.42g  19.53g
  /dev/sda3  os   lvm2 a--  158.97g 158.97g
  /dev/sdb1       lvm2 a--  232.88g 232.88g
```

Since we do not need anymore for the physical volume ``/dev/sdb1`` , remove it from the LVM layout
```
# pvremove /dev/sdb1
  Labels on physical volume "/dev/sdb1" successfully wiped
# pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda2  os   lvm2 a--   73.42g  19.53g
  /dev/sda3  os   lvm2 a--  158.97g 158.97g
```

Recreate the ``/dev/os/data`` logical volume with the remaining space in the ``os`` volume group
```
# lvcreate -l 100%FREE -n data os
WARNING: xfs signature detected on /dev/os/data at offset 0. Wipe it? [y/n] y
  Wiping xfs signature on /dev/os/data.
  Logical volume "data" created
# lvscan
  ACTIVE            '/dev/os/root' [50.00 GiB] inherit
  ACTIVE            '/dev/os/swap' [3.89 GiB] inherit
  ACTIVE            '/dev/os/data' [178.50 GiB] inherit
```

Format the volume group just created, mount it as ``/data`` fyle system and restore the data
```
# mkfs.xfs -f /dev/os/data
meta-data=/dev/os/data           isize=256    agcount=4, agsize=11698432 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=46793728, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=22848, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

# mount -a
#
# df -Th
Filesystem          Type      Size  Used Avail Use% Mounted on
/dev/mapper/os-root xfs        50G  2.0G   48G   4% /
devtmpfs            devtmpfs  1.8G     0  1.8G   0% /dev
tmpfs               tmpfs     1.9G     0  1.9G   0% /dev/shm
tmpfs               tmpfs     1.9G  8.5M  1.8G   1% /run
tmpfs               tmpfs     1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sda1           xfs       497M  183M  315M  37% /boot
/dev/mapper/os-data xfs       179G   33M  179G   1% /data
#
# mv /dump/* /data/
```

Finally, change the partition type of ``/dev/sdb1`` back to Linux (no LVM), format as XFS and mount it as a standard physical partition
```
# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p

Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   8e  Linux LVM

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 83
Changed type of partition 'Linux LVM' to 'Linux'

Command (m for help): p

Disk /dev/sdb: 250.1 GB, 250059350016 bytes, 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0004da93

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048   488397167   244197560   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
# mkfs.xfs -f /dev/sdb1
meta-data=/dev/sdb1              isize=256    agcount=4, agsize=15262348 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=61049390, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=29809, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

# mount -a
# df -Th
Filesystem          Type      Size  Used Avail Use% Mounted on
/dev/mapper/os-root xfs        50G  2.0G   48G   4% /
devtmpfs            devtmpfs  1.8G     0  1.8G   0% /dev
tmpfs               tmpfs     1.9G     0  1.9G   0% /dev/shm
tmpfs               tmpfs     1.9G  8.5M  1.8G   1% /run
tmpfs               tmpfs     1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sda1           xfs       497M  183M  315M  37% /boot
/dev/mapper/os-data xfs       179G   33M  179G   1% /data
/dev/sdb1           xfs       233G   33M  233G   1% /cinder-volumes
#
```


text:
## Samba server and Windows file sharing
Samba is an open source implementation of the SMB/CIFS protocol. It allows the networking of Microsoft Windows®, Linux, UNIX, and other operating systems. Samba allows a Linux/Unix server to appear as a Windows server to Windows clients.

With Samba, an administrator can do:

1. Serve directory trees and printers to Linux, UNIX, and Windows clients
2. Assist in network browsing with or without NetBIOS
3. Authenticate Windows domain logins
4. Provide WINS name server resolution

Samba is comprised of **smb**, **nmb**, and **winbind** services.

The ``smbd`` server daemon provides file sharing and printing services to Windows clients. In addition, it is responsible for user authentication, resource locking, and data sharing through the SMB protocol. The default ports on which the server listens for SMB traffic are TCP ports 139 and 445.

The ``nmbd`` server daemon understands and replies to NetBIOS name service requests produced by SMB in Windows-based systems. The default port that the server listens to for NMB traffic is UDP port 137.

The ``winbindd`` service resolves user and group information received from a server running Windows. This makes Windows user and group information understandable by Linux and UNIX platforms. This allows Windows domain users to appear and operate as Linux and UNIX users on a Linux or UNIX machine. Both ``winbindd`` and ``smbd`` are bundled with the Samba distribution, but the ``winbindd`` service is controlled separately from the ``smbd`` service.

#### Setup a Samba server
We'll setup a Samba server to make Linux file sharing available to Windows clients. Install the Samba package, enable and start the ``smbd`` and ``nmbd`` services

```
# yum install samba
# systemctl enable smb
# systemctl enable nmb
# systemctl start smb
# systemctl start nmb
```

Samba uses ``/etc/samba/smb.conf`` as its configuration file.

```
# mv /etc/samba/smb.conf /etc/samba/smb.conf.orig
# vi /etc/samba/smb.conf

# =============== Global configuration ===============
[global]
; Windows workgroup name and server description
workgroup = WORKGROUP
server string = My SMB Server %v
; NetBIOS name as the Linux machine will appear in Windows clients
netbios name = MYSMBSERVER
; interfaces where the service is listening: localhost and ens32 interfaces
interfaces = lo ens32
; users passwords database backend and location
passdb backend = smbpasswd
smb passwd file = /etc/samba/smbpasswd
; permitted hosts to use the Samba server: localhost and all host belonging to 10.10.10.0/24 subnet
hosts allow = 127. 10.10.10.
; protocol version
max protocol = SMB3
; type of security
security = user
; no printing services
printing = bsd
printcap name = /dev/null

# =============== Shares configuration ===============
[share1]
comment = Private Documents
; path of files to share
path = /samba/admin/data
; users admitted to use the file sharing service
valid users = admin
invalid users = user2 user3
; no guest user is admitted
guest ok = no
; make the share writable as Samba make it as readonly by default
writable = yes
; make the share visible as shared folder
browsable = yes

[share2]
comment = Public Documents
path = /samba/user2/data
valid users = user2 admin
guest ok = no
writable = yes
browsable = yes

[share3]
comment = Public Documents
path = /samba/user3/data
valid users = user3 admin
guest ok = no
writable = yes
browsable = yes
```

The Samba configuration file can be checked by the ``testparm`` command
```
# testparm /etc/samba/smb.conf
Load smb config files from /etc/samba/smb.conf
rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384)
Processing section "[homes]"
Processing section "[admin]"
Processing section "[guest]"
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
```

#### User access
More than one user can be admitted to access the same share. In the case above, the share1 is only accesible to the "admin" user. The share2 is accessible to "admin" and "user2" users but not "user3". The share3 is accessible to "admin" and "user3" to "user2".

**Note:** the connection to shares by the same Windows client needs to use the same user name. In our case, a Windows client can access all the shares above as "admin" but cannot access to share2 as "user2" AND access to share3 as "user3". If the Windows client needs to access with different users, it needs to logout from the previous user and then login again with a different user. Since Windows caches the login user, it needs to force the logout by issuing the command: ``net use * /delete`` from the Windows command shell

```
Microsoft Windows [Versione 10.0.10240]
(c) 2015 Microsoft Corporation. Tutti i diritti sono riservati.
C:\Users\Adriano>net use * /delete
Connessioni remote presenti:
                    \\10.10.10.12\IPC$
Continuando si annulleranno le connessioni.
Continuare questa operazione? (S/N) [N]: S
Esecuzione comando riuscita.
```
Samba uses different type of security. In the case above, the method is based on user level (default). With this method, each share is assigned specific users that can access it. When a user requests a connection to a share, Samba authenticates by validating the given username and password with the authorized users in the configuration file and the passwords in the password database of the Samba server.

Samba uses different database backends for storing users passwords. The simplest is store the password in a file called ``smbpasswd`` similar to the ``/etc/passwd`` file. Usually this file is located under ``/var/lib/samba/private/smbpasswd`` but location can be changed.

Add the user and set password in the Samba user database

```
# smbpasswd -a admin
New SMB password:
Retype new SMB password:
#
```
The ``pdbedit`` command lists the Samba users database

```
# pdbedit -L
admin:1000:
user1:1001:
user2:1002:
user3:1003:
```

Other security methods: domain and server level security are deprecated in latest Samba.

With smbpasswd database backend, a Samba user should exist as valid user in the Linux machine. To secure the Linux machine preventing login from Samba users, you should disable the login from these users
```
# useradd -d /samba/share user1
# usermod -s /bin/false user1
# cat /etc/passwd | grep user1
user1:x:1003:1002::/samba/share:/sbin/nologin
#
# ssh user1@localhost
user1@localhost's password:
Last login: Tue Sep 15 11:50:08 2015
This account is currently not available.
Connection to localhost closed.
#
# sftp user1@localhost
user1@localhost's password:
subsystem request failed on channel 0
Couldn't read packet: Connection reset by peer
```
Alternatively, you can leave the ssh but should chroot the user's home directory.

#### File permissions and attributes
In our example above, we are going to share Linux files and folders to Windows clients. Since Windows and Linux use different approach to file permissions and attributes, Samba will take care of mapping the two approaches.

All Linux files have read, write, and execute bits for three classifications of users: owner (u), group (g), and rest of the world (o). Windows, on the other hand, has four principal bits that it uses with any file: read-only, system, hidden, and archive:

1. Read-only. The file's contents can be read by a user but cannot be written to.
2. System. This file has a specific purpose required by the operating system.
3. Hidden. This file has been marked to be invisible to the user, unless the operating systems is explicitly set to show it.
4. Archive. This file has been touched since the last backup was performed on it.

There is no bit to specify that a file is executable since Windows identifies executable files by looking at the file extension. Windows files stored on a Linux Samba share have their own attributes that need to be preserved. Samba preserves these bits by reusing the Linux executable permission bits of the file, if it is instructed to do so. Mapping these bits, however, has a side-effect: if a Windows user stores a file in a Samba share, at Linux side, some of the executable bits are set.

The Samba options deciding the mapping
```
[share]
...
	store dos attributes = yes
	map archive = yes ;default is yes
	map system = yes  ;default is no
	map hidden = yes  ;default is no
```
The last three options map the archive, system, and hidden attributes to the owner, group, and world execute bits of the file, respectively. In the example above, the options are used on a per-share basis. Setting them globally makes them the default for all shares. The first option also makes sure that Samba does not change the Windows permission bits.

**Note:** These options can be used if the Linux file system supports the extended attributes, and those attributes are enabled, usually via the ``user_xattr`` mount option in the ``/etc/fstab`` file. Unlike _ext3_ and _ext4_, the _xfs_ file system enables the ``user_xattr`` option by default.

Samba has the ``create mask`` and the ``directory mask`` options to help with files and folders creation. The creation masks help to define the permissions a file or directory at the time it is created. On the Linux side, you can control what permissions a file or directory have when it is created. On the Windows side, you can disable the read-only, archive, system, and hidden attributes of a file as well.

```
[share]
...
	store dos attributes = yes
	map archive = yes            ;default is yes
	map system = yes             ;default is no
	map hidden = yes             ;default is no
	create mask = 0744           ;default is 0744
	directory mask = 0755        ;default is 0755
```

On the Linux side, new files and folders will look like

```
# ll /samba/share/user1
total 0
-rwxr--r-- 1 user1 samba 0 Sep 15 13:00 mydocument.txt
drwxr-xr-x 2 user1 samba 6 Sep 15 13:00 myfolder
```

It is possible force various bits with the ``force create mode`` and ``force directory mode`` options. With the ``create mask`` and ``create directory mask`` options, the administrator allow the permission bits to be set by the requested user. On the other side, the ``force create mode`` and ``force directory mode`` will force a particular bit to be set, even if it wasn’t requested by the user.

At the same time, it is possible to force the Linux user and group attributes of a file that is created on the Windows side by the ``force user`` and the ``force group`` options.

```
[share]
...
	store dos attributes = yes
	map archive = yes            ;default is yes
	map system = yes             ;default is no
	map hidden = yes             ;default is no
	create mask = 0744           ;default is 0744
	directory mask = 0755        ;default is 0755
	force create mode = 0000     ;default is 0000
	force directory mode = 0000  ;default is 0000
	force user = user1
	force group samba
```