Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge architecture_2024 branch into master #1177

Merged
merged 380 commits into from
May 6, 2024
Merged

Conversation

imobachgs
Copy link
Contributor

@imobachgs imobachgs commented May 3, 2024

After a few months of work, it is time to merge the architecture_2024 branch into master. It is still a work-in-progress, but all the efforts should be go now against that branch.

Pull requests

Other commits

imobachgs and others added 30 commits March 21, 2024 21:50
## Problem

Questions are not exposed in new architecture 2024


## Solution

Add path to enlist questions and also announce when question is answered
or new appear on websocket.


## Testing

- *Tested manually*
# Implementation PBI description
---

In the previous PBI we documented a possible API and also created a POC
but it just allowed to query some configuration, so we have extended the
PR with the API implementation

## Implemented Network API

<details>
  <summary>Resource <b>/network/state</b></summary>
  
  - GET: get the current network state and general information 
  
  **Request example**
  
  ```json
$ curl -s localhost:3000/api/network/state -H @headers.txt | j
{
  "connectivity": true,
  "wireless_enabled": false,
  "networking_enabled": true
}
```

  - PUT: Update the current network state (currently only enabling wireless is supported)
  
  **Request example**

  ```json

$ cat state.json 
{
  "connectivity": true,
  "wireless_enabled": true,
  "networking_enabled": true
}
  
$ curl -s -X POST localhost:3000/api/network/state -H @headers.txt -H "Content-Type: application/json" -d @state.json  | jq
{
  "connectivity": true,
  "wireless_enabled": true,
  "networking_enabled": true
}
```
  
</details>
  
<details>
  <summary>Resource <b>/network/devices</b></summary>
  
  - GET: list of known devices
    - Attributes
      - Name: String
      - Type: Enum


**Request example**

```json
$ curl -s localhost:3000/network/devices -H @headers.txt | jq
[
  {
    "name": "enp2s0f0",
    "type": "Ethernet"
  },
  {
    "name": "wlp3s0",
    "type": "Wireless"
  },
  {
    "name": "eth0",
    "type": "Ethernet"
  }
 ``` 
</details>

<details>

<summary>Resource <b>/network/connections</b></summary>

  - GET: list of managed / known connections
  **Request example**
  
  ```json
$curl -s localhost:3000/api/network/connections -H @headers.txt | jq
[
  {
    "id": "lo",
    "method4": "manual",
    "method6": "manual",
    "addresses": [
      "127.0.0.1/8",
      "::1"
    ],
    "interface": "lo"
  },
  {
    "id": "Wired connection 1",
    "method4": "manual",
    "gateway4": "192.168.0.1",
    "method6": "auto",
    "addresses": [
      "192.168.0.230/24"
    ],
    "nameservers": [
      "192.168.0.1"
    ],
    "interface": "eth0"
  },
  {
    "id": "AgamaNetwork",
    "method4": "disabled",
    "method6": "disabled",
    "wireless": {
      "password": "agama.test",
      "security": "wpa-psk",
      "ssid": "AgamaNetwork2",
      "mode": "infrastructure"
    }
  }
]
```

 - POST: create a new connection
 ** Request example **

```json
$ curl -X POST localhost:3000/api/network/connections -H @headers.txt -H "Content-Type: application/json" -d @data_wifi.json
"ce91e1b8-7da4-4bff-a286-91610a8cb762"
```

####  /network/connections/:id
  - GET: find a connection by its uuid or id **(not implemented)**
  - PATCH: update connection
  - DELETE: remove the connection

The attributes for updating a connection or creating a new one could
follow the same schema used for the profile:

```json
      "connections": {
        "description": "Network connections to be defined",
        "type": "array",
        "items": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "id": {
              "description": "Connection ID",
              "type": "string"
            },
            "interface": {
              "description": "The name of the network interface bound to this connection",
              "type": "string"
            },
            "mac-address": {
              "description": "Custom mac-address (can also be 'preserve', 'permanent', 'random' or 'stable')",
              "type": "string"
            },
            "method4": {
              "description": "IPv4 configuration method (e.g., 'auto')",
              "type": "string",
              "enum": [
                "auto",
                "manual",
                "link-local",
                "disabled"
              ]
            },
            "method6": {
              "description": "IPv6 configuration method (e.g., 'auto')",
              "type": "string",
              "enum": [
                "auto",
                "manual",
                "link-local",
                "disabled"
              ]
            },
            "gateway4": {
              "description": "Connection gateway address (e.g., '192.168.122.1')",
              "type": "string"
            },
            "gateway6": {
              "description": "Connection gateway address (e.g., '::ffff:c0a8:7a01')",
              "type": "string"
            },
            "addresses": {
              "type": "array",
              "items": {
                "description": "Connection addresses",
                "type": "string",
                "additionalProperties": false
              }
            },
            "nameservers": {
              "type": "array",
              "items": {
                "description": "Nameservers (IPv4 and/or IPv6 are allowed)",
                "type": "string",
                "additionalProperties": false
              }
            },
            "wireless": {
              "type": "object",
              "description": "Wireless configuration",
              "additionalProperties": false,
              "properties": {
                "password": {
                  "type": "string"
                },
                "security": {
                  "type": "string"
                },
                "ssid": {
                  "type": "string"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "infrastructure",
                    "adhoc",
                    "mesh",
                    "ap"
                  ]
                }
              }
            },
            "bond": {
              "type": "object",
              "description": "Bonding configuration",
              "additionalProperties": false,
              "properties": {
                "mode": {
                  "type": "string"
                },
                "options": {
                  "type": "string"
                },
                "ports": {
                  "type": "array",
                  "items": {
                    "description": "A list of the interfaces or connections to be bonded",
                    "type": "string",
                    "additionalProperties": false
                  }
                }
              }
            },
            "match": {
              "type": "object",
              "description": "Match settings",
              "additionalProperties": false,
              "properties": {
                "kernel": {
                  "type": "array",
                  "items": {
                    "description": "A list of kernel command line arguments to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "interface": {
                  "type": "array",
                  "items": {
                    "description": "A list of interface names to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "driver": {
                  "type": "array",
                  "items": {
                    "description": "A list of driver names to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "path": {
                  "type": "array",
                  "items": {
                    "description": "A list of paths to match against the ID_PATH udev property of devices",
                    "type": "string",
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "required": [
            "id"
          ]
```

Which means that for bringing up or down an specific connection / device
could need an specific method or it could be handle as any other
attribute.
  
  </details>

<details>
  <summary>Resource <b>/network/wifi</b></summary>

  - GET: list of scanned WiFi networks
  **Request example**

```json
$curl -s localhost:3000/api/network/wifi -H @headers.txt | jq
[
  "Agama",
  "Agama2"
]

```

</details>

<details>
  <summary>Resource <b>/network/system/apply</b></summary>

  - PUT: Apply the changes to the system
  **Request example**

```json
curl -s -X PUT localhost:3000/api/network/system/apply -H @headers.txt | jq
null
```
</details>

## Testing

<details>
  <summary><b>Tested manually</b></summary>

```bash
suse@vikingo-laptop:~$ ./generate_headers.sh 
Obtained token 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MTEwMzU4MDV9.nifdrxlq3ZKK4LoVjY-2sPb9ZzXIq5M3Xxqudy8zqvE'
suse@vikingo-laptop:~$ ./get_state.sh 
{
  "connectivity": true,
  "wireless_enabled": true,
  "networking_enabled": true
}
suse@vikingo-laptop:~$ ./get_connections.sh 
[
  {
    "id": "lo",
    "method4": "manual",
    "method6": "manual",
    "addresses": [
      "127.0.0.1/8",
      "::1"
    ],
    "interface": "lo"
  },
  {
    "id": "Wired connection 1",
    "method4": "manual",
    "gateway4": "192.168.0.1",
    "method6": "auto",
    "addresses": [
      "192.168.0.230/24"
    ],
    "nameservers": [
      "192.168.0.1"
    ],
    "interface": "eth0"
  },
  {
    "id": "AgamaNetwork",
    "method4": "disabled",
    "method6": "disabled",
    "wireless": {
      "password": "agama.test",
      "security": "wpa-psk",
      "ssid": "AgamaNetwork2",
      "mode": "infrastructure"
    }
  }
]
suse@vikingo-laptop:~$ ./get_wifis.sh 
[
  "AgamaNetwork",
  "AgamaNetwork2",
]

<details>
  <summary>Resource <b>/network/system/apply</b></summary>
  - PUT: Appl  list of scanned WiFi networks
  **Request example**
curl -s -X PUT localhost:3000/api/network/system/apply -H @headers.txt | jq

# Scripts used for obtain and modify the configuration

suse@vikingo-laptop:~$ cat generate_headers.sh 
#!/bin/bash

TOKEN=$(curl -s -X POST localhost:3000/api/auth -H 'Content-Type: application/json' -d '{"password": "agama.auth"}' | jq -r ".token")
echo "Obtained token '${TOKEN}'"

echo -n "Authorization: Bearer " >headers.txt
echo $TOKEN >>headers.txt
suse@vikingo-laptop:~$ cat get_connections.sh 
#!/bin/bash

curl -s localhost:3000/api/network/connections -H @headers.txt | jq
suse@vikingo-laptop:~$ cat get_wifis.sh 
#!/bin/bash

curl -s localhost:3000/api/network/wifi -H @headers.txt | jq
suse@vikingo-laptop:~$ cat get_state.sh 
#!/bin/bash

curl -s localhost:3000/api/network/state -H @headers.txt | jq
cat change_state.sh 
#!/bin/bash

curl -X POST localhost:3000/api/network/state -H @headers.txt -H "Content-Type: application/json" -d @state.json


```

</details>

# Documentation PBI description
---

## Problem

We would like to expose the Networking API over http which is currently
not available.

## Solution

Document an HTTP alternative as well as provide a POC exposing it.

## API Design

Our Rest API could expose the general state and configuration of the
network as well as the devices and connections resources below the
network namespace as shown below:

<details>
  <summary>Resource <b>/network/state</b></summary>
  
  - GET: get the current network state and general information 
  
</details>

<details>
  <summary>Resource <b>/network/config</b></summary>
  
  - GET: get the general configuration like wireless enabled or not
  - PATCH: update general configuration
  
</details>
  
<details>
  <summary>Resource <b>/network/devices</b></summary>
  
  - GET: list of known devices
    - Attributes
      - Name: String
      - Type: Enum

#### /network/devices/:name
  - GET: find a device by its name

**Request example**

```json
$ curl -s localhost:3000/network/devices -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDkzOTEzMDN9.RYUSttHGhGiqmSDy01Kf3-fripqohA3Li0pIneb-t_Y' | jq
[
  {
    "name": "enp2s0f0",
    "type": "Ethernet"
  },
  {
    "name": "wlp3s0",
    "type": "Wireless"
  },
  {
    "name": "eth0",
    "type": "Ethernet"
  }
 ``` 
</details>

<details>

<summary>Resource <b>/network/connections</b></summary>

  - GET: list of managed / known connections
  - POST: create a new connection
  **Request example**
  
  ```json
  suse@vikingo-laptop:~$ curl -s localhost:3000/network/connections -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDkzOTEzMDN9.RYUSttHGhGiqmSDy01Kf3-fripqohA3Li0pIneb-t_Y' | jq
[
  {
    "id": "Wired connection 1",
    "uuid": "530d40c2-c580-43a7-b93e-c443702529a2",
    "mac_address": "",
    "ip_config": {
      "method4": "Manual",
      "method6": "Auto",
      "addresses": [
        "192.168.0.230/24"
      ],
      "nameservers": [
        "192.168.0.1"
      ],
      "gateway4": "192.168.0.1",
      "routes4": [
        {
          "destination": "0.0.0.0/24",
          "next_hop": "192.168.0.1"
        }
      ],
      "routes6": []
    },
    "status": "Up",
    "interface": "eth0",
    "port_config": "None",
    "match_config": {},
    "config": "Ethernet"
  },
  {
    "id": "AgamaTest",
    "uuid": "e7c684d5-f8e9-43a0-b303-decfe2883e53",
    "mac_address": "",
    "ip_config": {
      "method4": "Auto",
      "method6": "Auto",
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "wlp3s0",
    "port_config": "None",
    "match_config": {},
    "config": {
      "Wireless": {
        "mode": "Infra",
        "ssid": "AgamaTest",
        "security": "WPA2",
        "wep_security": {
          "auth_alg": "Open",
          "wep_key_type": "Unknown",
          "wep_key_index": 0
        },
        "hidden": false
      }
    }
  },
  {
    "id": "AgamaTest2",
    "uuid": "bc323ed0-18d8-4f85-b90e-5b7907e3b711",
    "mac_address": "",
    "ip_config": {
      "method4": "Auto",
      "method6": "Auto",
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "wlp3s0",
    "port_config": "None",
    "match_config": {},
    "config": {
      "Wireless": {
        "mode": "Infra",
        "ssid": "AgamaTest2",
        "security": "WPA2",
        "wep_security": {
          "auth_alg": "Open",
          "wep_key_type": "Unknown",
          "wep_key_index": 0
        },
        "hidden": false
      }
    }
  },
  {
    "id": "lo",
    "uuid": "66d7c54a-735a-42c6-b412-572a1134efec",
    "mac_address": "",
    "ip_config": {
      "method4": "Manual",
      "method6": "Manual",
      "addresses": [
        "127.0.0.1/8",
        "::1"
      ],
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "lo",
    "port_config": "None",
    "match_config": {},
    "config": "Loopback"
  }
]
```

####  /network/connections/:id
  - GET: find a connection by its uuid or id
  - PATCH: update connection
  - DELETE: remove the connection

The attributes for updating a connection or creating a new one could
follow the same schema used for the profile:

```json
      "connections": {
        "description": "Network connections to be defined",
        "type": "array",
        "items": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "id": {
              "description": "Connection ID",
              "type": "string"
            },
            "interface": {
              "description": "The name of the network interface bound to this connection",
              "type": "string"
            },
            "mac-address": {
              "description": "Custom mac-address (can also be 'preserve', 'permanent', 'random' or 'stable')",
              "type": "string"
            },
            "method4": {
              "description": "IPv4 configuration method (e.g., 'auto')",
              "type": "string",
              "enum": [
                "auto",
                "manual",
                "link-local",
                "disabled"
              ]
            },
            "method6": {
              "description": "IPv6 configuration method (e.g., 'auto')",
              "type": "string",
              "enum": [
                "auto",
                "manual",
                "link-local",
                "disabled"
              ]
            },
            "gateway4": {
              "description": "Connection gateway address (e.g., '192.168.122.1')",
              "type": "string"
            },
            "gateway6": {
              "description": "Connection gateway address (e.g., '::ffff:c0a8:7a01')",
              "type": "string"
            },
            "addresses": {
              "type": "array",
              "items": {
                "description": "Connection addresses",
                "type": "string",
                "additionalProperties": false
              }
            },
            "nameservers": {
              "type": "array",
              "items": {
                "description": "Nameservers (IPv4 and/or IPv6 are allowed)",
                "type": "string",
                "additionalProperties": false
              }
            },
            "wireless": {
              "type": "object",
              "description": "Wireless configuration",
              "additionalProperties": false,
              "properties": {
                "password": {
                  "type": "string"
                },
                "security": {
                  "type": "string"
                },
                "ssid": {
                  "type": "string"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "infrastructure",
                    "adhoc",
                    "mesh",
                    "ap"
                  ]
                }
              }
            },
            "bond": {
              "type": "object",
              "description": "Bonding configuration",
              "additionalProperties": false,
              "properties": {
                "mode": {
                  "type": "string"
                },
                "options": {
                  "type": "string"
                },
                "ports": {
                  "type": "array",
                  "items": {
                    "description": "A list of the interfaces or connections to be bonded",
                    "type": "string",
                    "additionalProperties": false
                  }
                }
              }
            },
            "match": {
              "type": "object",
              "description": "Match settings",
              "additionalProperties": false,
              "properties": {
                "kernel": {
                  "type": "array",
                  "items": {
                    "description": "A list of kernel command line arguments to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "interface": {
                  "type": "array",
                  "items": {
                    "description": "A list of interface names to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "driver": {
                  "type": "array",
                  "items": {
                    "description": "A list of driver names to match",
                    "type": "string",
                    "additionalProperties": false
                  }
                },
                "path": {
                  "type": "array",
                  "items": {
                    "description": "A list of paths to match against the ID_PATH udev property of devices",
                    "type": "string",
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "required": [
            "id"
          ]
```

Which means that for bringing up or down an specific connection / device
could need an specific method or it could be handle as any other
attribute.
  
  </details>

<details>
  <summary>Resource <b>/network/wifi_networks</b></summary>

  - GET: list of scanned wifi networks

</details>

**Note:** Which attributes should be required and exposed needs to be
discussed, and probably we should expose the persistent and running
configuration maybe as part of the same resource or separately.

<details>
<summary>Example of the <b>OpenAPI</b> generated documentation based on
the implemented <b>POC code</b></summary>

```json
{
  "openapi": "3.0.3",
  "info": {
    "title": "agama-dbus-server",
    "description": "Agama web API description",
    "license": {
      "name": ""
    },
    "version": "0.1.0"
  },
  "paths": {
    "/network/connections": {
      "get": {
        "tags": [
          "crate::network::web"
        ],
        "operationId": "connections",
        "responses": {
          "200": {
            "description": "List of known connections",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Connection"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/network/devices": {
      "get": {
        "tags": [
          "crate::network::web"
        ],
        "operationId": "devices",
        "responses": {
          "200": {
            "description": "List of devices",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Device"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Connection": {
        "type": "object",
        "description": "Represents a known network connection.",
        "required": [
          "id",
          "uuid",
          "mac_address",
          "ip_config",
          "status",
          "port_config",
          "match_config",
          "config"
        ],
        "properties": {
          "config": {
            "$ref": "#/components/schemas/ConnectionConfig"
          },
          "controller": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              }
            ],
            "nullable": true
          },
          "id": {
            "type": "string"
          },
          "interface": {
            "type": "string",
            "nullable": true
          },
          "ip_config": {
            "$ref": "#/components/schemas/IpConfig"
          },
          "mac_address": {
            "$ref": "#/components/schemas/MacAddress"
          },
          "match_config": {
            "$ref": "#/components/schemas/MatchConfig"
          },
          "port_config": {
            "$ref": "#/components/schemas/PortConfig"
          },
          "status": {
            "$ref": "#/components/schemas/Status"
          },
          "uuid": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "Device": {
        "type": "object",
        "description": "Network device",
        "required": [
          "name",
          "type"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/DeviceType"
          }
        }
      },
      "DeviceType": {
        "type": "string",
        "enum": [
          "Loopback",
          "Ethernet",
          "Wireless",
          "Dummy",
          "Bond",
          "Vlan",
          "Bridge"
        ]
      },
      "NetworkState": {
        "type": "object",
        "required": [
          "devices",
          "connections"
        ],
        "properties": {
          "connections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Connection"
            }
          },
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Device"
            }
          }
        }
      }
    }
  }
}
```

</details>

### Signals / Websocket notifications

With **websockets** we can carry more information than what is usually
emitted over **DBUS** therefore we could subscribe to **DBUS** signals
in the backend for the different resources submitting more information
over the websocket, for example for any new device connected or any
change in a connection property but have not gone over what to notify so
far as we are not subscribing to signals in the backend at all and we
are only sending when a connections has been added or removed.

## Testing

<details>
  <summary><b>Tested manually</b></summary>

```bash
$ curl -s -X POST localhost:3000/authenticate -H 'Content-Type: application/json' -d '{"password": "your_password"}' | jq -r ".token"

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDkzOTEzMDN9.RYUSttHGhGiqmSDy01Kf3-fripqohA3Li0pIneb-t_Y

$ curl -s localhost:3000/network/devices -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDkzOTEzMDN9.RYUSttHGhGiqmSDy01Kf3-fripqohA3Li0pIneb-t_Y' | jq
[
  {
    "name": "enp2s0f0",
    "type": "Ethernet"
  },
  {
    "name": "wlp3s0",
    "type": "Wireless"
  },
  {
    "name": "eth0",
    "type": "Ethernet"
  }
suse@vikingo-laptop:~$ curl -s localhost:3000/network/connections -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDkzOTEzMDN9.RYUSttHGhGiqmSDy01Kf3-fripqohA3Li0pIneb-t_Y' | jq
[
  {
    "id": "Wired connection 1",
    "uuid": "530d40c2-c580-43a7-b93e-c443702529a2",
    "mac_address": "",
    "ip_config": {
      "method4": "Manual",
      "method6": "Auto",
      "addresses": [
        "192.168.0.230/24"
      ],
      "nameservers": [
        "192.168.0.1"
      ],
      "gateway4": "192.168.0.1",
      "routes4": [
        {
          "destination": "0.0.0.0/24",
          "next_hop": "192.168.0.1"
        }
      ],
      "routes6": []
    },
    "status": "Up",
    "interface": "eth0",
    "port_config": "None",
    "match_config": {},
    "config": "Ethernet"
  },
  {
    "id": "AgamaTest",
    "uuid": "e7c684d5-f8e9-43a0-b303-decfe2883e53",
    "mac_address": "",
    "ip_config": {
      "method4": "Auto",
      "method6": "Auto",
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "wlp3s0",
    "port_config": "None",
    "match_config": {},
    "config": {
      "Wireless": {
        "mode": "Infra",
        "ssid": "AgamaTest",
        "security": "WPA2",
        "wep_security": {
          "auth_alg": "Open",
          "wep_key_type": "Unknown",
          "wep_key_index": 0
        },
        "hidden": false
      }
    }
  },
  {
    "id": "AgamaTest2",
    "uuid": "bc323ed0-18d8-4f85-b90e-5b7907e3b711",
    "mac_address": "",
    "ip_config": {
      "method4": "Auto",
      "method6": "Auto",
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "wlp3s0",
    "port_config": "None",
    "match_config": {},
    "config": {
      "Wireless": {
        "mode": "Infra",
        "ssid": "AgamaTest2",
        "security": "WPA2",
        "wep_security": {
          "auth_alg": "Open",
          "wep_key_type": "Unknown",
          "wep_key_index": 0
        },
        "hidden": false
      }
    }
  },
  {
    "id": "lo",
    "uuid": "66d7c54a-735a-42c6-b412-572a1134efec",
    "mac_address": "",
    "ip_config": {
      "method4": "Manual",
      "method6": "Manual",
      "addresses": [
        "127.0.0.1/8",
        "::1"
      ],
      "routes4": [],
      "routes6": []
    },
    "status": "Up",
    "interface": "lo",
    "port_config": "None",
    "match_config": {},
    "config": "Loopback"
  }
]

```

</details>
The initial idea was to adapt the software page and the patterns
selector to the new HTTP-based API. However, we took the chance to
revamp the software page to make it more similar to other Agama parts.

<details>
  <summary>New software page</summary>


![software-page](https://github.com/openSUSE/agama/assets/15836/4c603bed-3fca-41fe-88b2-638eb523f8ba)
</details>

<details>
  <summary>New patterns selector</summary>


![software-selection](https://github.com/openSUSE/agama/assets/15836/5a672682-d172-4c1b-bede-5bfff900e831)
</details>

## Changes summary

* Introduce a new software page that lists the patterns to install.
* Move the patterns selector to a pop-up.
* Introduce small changes to the software API.
* Update the JavaScript tests and enable the type checking on the new
code.

## What is missing

- [ ] Distinguish between user and automatically selected patterns.

## Out of scope

* Improve the wording.
Rename the authentication token
mchf and others added 22 commits April 26, 2024 10:01
## Problem

Security audit

- *Bugzilla link*](https://bugzilla.suse.com/show_bug.cgi?id=1219688)

## Solution

a few sentences about security mechanism in agama's web server
Co-authored-by: Imobach González Sosa <[email protected]>
This reverts commit c59cd17.
Trello:
https://trello.com/c/KYDDRo30/3630-8-display-the-running-network-configuration

This PR adds support for tracking the status of the network devices and
displaying that information through the web UI.

## Extending the networking model

Now the `Device` struct includes information about [its current
state](https://github.com/openSUSE/agama/blob/d5f7da8d4b9f673f08348af6c7582cd65b414019/rust/agama-server/src/network/model.rs#L465-L468),
including its IP configuration, MAC address, device state, etc.

To keep this information up-to-date, we introduced the concept of
[network
watchers](https://github.com/openSUSE/agama/blob/d5f7da8d4b9f673f08348af6c7582cd65b414019/rust/agama-server/src/network/adapter.rs#L38)
which listens for events in the corresponding backend and update the
network model accordingly. We implemented a [NetworkManager
Watcher](https://github.com/openSUSE/agama/blob/d5f7da8d4b9f673f08348af6c7582cd65b414019/rust/agama-server/src/network/nm/watcher.rs).

```
+----------+  actions    +---------------+   actions   +---------------+
|  Watcher |---------->  | Network Model | <---------->| HTTP/JSON API |
+----------+             +---------------+    events   +---------------+
      |
      | listens
+----------------+
| NetworkManager +
+----------------+
```

## Adapting the UI

When it comes to the web UI, we decided to make it work with the new
updates mechanism, but nothing else. We plan to invest some time in
rethinking that part of the UI (as we did for storge), but not now.

## Screenshots

<details>
<summary>Overview with a single device</summary>

![Overview 1
device](https://github.com/openSUSE/agama/assets/7056681/d538202c-e7e8-4629-b22a-9faa71761bf4)
</details>

<details>
<summary>Overview with two devices</summary>

![Overview 2
devices](https://github.com/openSUSE/agama/assets/7056681/8e41fd1e-41d3-4977-937e-7cf20f761c0c)
</details>

<details>
<summary>Network page including wired and wireless devices</summary>

![Network
Page](https://github.com/openSUSE/agama/assets/7056681/0cf374a8-f589-4126-bbb8-81415551e0a0)
</details>

<details>
<summary>Editing a wired connection</summary>

![Edit
wired](https://github.com/openSUSE/agama/assets/7056681/6ab68963-08df-4fca-a70a-eb8c46a4d715)
</details>

<details>
<summary>Editing a wireless connection</summary>

![Edit
wireless](https://github.com/openSUSE/agama/assets/7056681/19f122ce-cd74-40d0-9cf9-c65533d99e95)
</details>
Co-authored-by: Imobach González Sosa <[email protected]>
It is the first step in having HTTP based API for storage. As it is
really big API we decided to split it into series of patches for easier
review.
@coveralls
Copy link

coveralls commented May 3, 2024

Coverage Status

coverage: 71.699% (-3.4%) from 75.054%
when pulling 6fb21b6 on merge-architecture_2024
into aa89adb on master.

Copy link
Contributor

@joseivanlopez joseivanlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything has been already reviewed, everything is green, so LGTM.

@imobachgs imobachgs merged commit 3353513 into master May 6, 2024
5 checks passed
@imobachgs imobachgs deleted the merge-architecture_2024 branch May 6, 2024 06:09
@imobachgs imobachgs mentioned this pull request May 17, 2024
imobachgs added a commit that referenced this pull request May 17, 2024
Prepare for releasing Agama 8. It includes the following pull requests:

* #884
* #886
* #914
* #918
* #956
* #957
* #958
* #959
* #960
* #961
* #962
* #963
* #964
* #965
* #966
* #969
* #970
* #976
* #977
* #978
* #979
* #980
* #981
* #983
* #984
* #985
* #986
* #988
* #991
* #992
* #995
* #996
* #997
* #999
* #1003
* #1004
* #1006
* #1007
* #1008
* #1009
* #1010
* #1011
* #1012
* #1014
* #1015
* #1016
* #1017
* #1020
* #1022
* #1023
* #1024
* #1025
* #1027
* #1028
* #1029
* #1030
* #1031
* #1032
* #1033
* #1034
* #1035
* #1036
* #1038
* #1039
* #1041
* #1042
* #1043
* #1045
* #1046
* #1047
* #1048
* #1052
* #1054
* #1056
* #1057
* #1060
* #1061
* #1062
* #1063
* #1064
* #1066
* #1067
* #1068
* #1069
* #1071
* #1072
* #1073
* #1074
* #1075
* #1079
* #1080
* #1081
* #1082
* #1085
* #1086
* #1087
* #1088
* #1089
* #1090
* #1091
* #1092
* #1093
* #1094
* #1095
* #1096
* #1097
* #1098
* #1099
* #1100
* #1102
* #1103
* #1104
* #1105
* #1106
* #1109
* #1110
* #1111
* #1112
* #1114
* #1116
* #1117
* #1118
* #1119
* #1120
* #1121
* #1122
* #1123
* #1125
* #1126
* #1127
* #1128
* #1129
* #1130
* #1131
* #1132
* #1133
* #1134
* #1135
* #1136
* #1138
* #1139
* #1140
* #1141
* #1142
* #1143
* #1144
* #1145
* #1146
* #1147
* #1148
* #1149
* #1151
* #1152
* #1153
* #1154
* #1155
* #1156
* #1157
* #1158
* #1160
* #1161
* #1162
* #1163
* #1164
* #1165
* #1166
* #1167
* #1168
* #1169
* #1170
* #1171
* #1172
* #1173
* #1174
* #1175
* #1177
* #1178
* #1180
* #1181
* #1182
* #1183
* #1184
* #1185
* #1187
* #1188
* #1189
* #1190
* #1191
* #1192
* #1193
* #1194
* #1195
* #1196
* #1198
* #1199
* #1200
* #1201
* #1203
* #1204
* #1205
* #1206
* #1207
* #1208
* #1209
* #1210
* #1211
* #1212
* #1213
* #1214
* #1215
* #1216
* #1217
* #1219
* #1220
* #1221
* #1222
* #1223
* #1224
* #1225
* #1226
* #1227
* #1229
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants