From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/kimchi/API.json | 134 -------- src/wok/plugins/kimchi/Makefile.am | 2 - src/wok/plugins/kimchi/control/host.py | 111 +------ src/wok/plugins/kimchi/docs/API.md | 285 ----------------- src/wok/plugins/kimchi/i18n.py | 54 ---- src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +-------- src/wok/plugins/kimchi/model/config.py | 21 -- src/wok/plugins/kimchi/model/host.py | 348 +-------------------- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +----- src/wok/plugins/kimchi/tests/test_model.py | 237 -------------- src/wok/plugins/kimchi/tests/test_rest.py | 54 ---- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - src/wok/plugins/kimchi/ui/js/src/kimchi.api.js | 317 ------------------- 17 files changed, 7 insertions(+), 1828 deletions(-) diff --git a/src/wok/plugins/kimchi/API.json b/src/wok/plugins/kimchi/API.json index fc1d2dd..6189207 100644 --- a/src/wok/plugins/kimchi/API.json +++ b/src/wok/plugins/kimchi/API.json @@ -59,30 +59,6 @@ } }, "properties": { - "debugreports_create": { - "type": "object", - "error": "KCHDR0006E", - "properties": { - "name": { - "description": "The name for the debug report file.", - "type": "string", - "pattern": "^[_A-Za-z0-9-]*$", - "error": "KCHDR0007E" - } - } - }, - "debugreport_update": { - "type": "object", - "properties": { - "name": { - "description": "New name of debug report", - "type": "string", - "pattern": "^[_A-Za-z0-9-]*$", - "error": "KCHDR0007E" - } - }, - "additionalProperties": false - }, "storagepools_create": { "type": "object", "error": "KCHPOOL0026E", @@ -684,116 +660,6 @@ "additionalProperties": false, "error": "KCHAPI0001E" }, - "repositories_create": { - "type": "object", - "properties": { - "repo_id": { - "description": "Repository ID used for YUM repository.", - "type": "string", - "error": "KCHREPOS0001E" - }, - "baseurl": { - "description": "URL to the directory where the repodata directory of a repository is located. Can be an http://, ftp:// or file:// URL.", - "type": "string", - "error": "KCHREPOS0002E" - }, - "config": { - "description": "Dictionary containing repository configuration", - "type": "object", - "error": "KCHREPOS0003E", - "properties": { - "dist": { - "description": "Distribution to DEB repository", - "type": "string", - "error": "KCHREPOS0004E" - }, - "comps": { - "description": "List of components to DEB repository", - "type": "array", - "error": "KCHREPOS0005E", - "uniqueItems": true, - "items": { - "description": "Component name", - "type": "string", - "error": "KCHREPOS0006E" - } - }, - "repo_name": { - "description": "YUM repository name", - "type": "string", - "error": "KCHREPOS0023E" - }, - "mirrorlist": { - "description": "URL to a file containing a list of baseurls", - "type": "string", - "error": "KCHREPOS0007E" - }, - "metalink": { - "description": "URL to a metalink file for the repomd.xml", - "type": "string", - "error": "KCHREPOS0029E" - } - } - } - }, - "additionalProperties": false, - "error": "KCHAPI0001E" - }, - "repository_update": { - "type": "object", - "properties": { - "baseurl": { - "description": "URL to the directory where the repodata directory of a repository is located. Can be an http://, ftp:// or file:// URL.", - "type": "string", - "error": "KCHREPOS0002E" - }, - "config": { - "description": "Dictionary containing repository configuration", - "type": "object", - "error": "KCHREPOS0003E", - "properties": { - "dist": { - "description": "Distribution to DEB repository", - "type": "string", - "error": "KCHREPOS0004E" - }, - "comps": { - "description": "List of components to DEB repository", - "type": "array", - "error": "KCHREPOS0005E", - "uniqueItems": true, - "items": { - "description": "Component name", - "type": "string", - "error": "KCHREPOS0006E" - } - }, - "repo_name": { - "description": "Human-readable string describing the YUM repository.", - "type": "string", - "error": "KCHREPOS0008E" - }, - "mirrorlist": { - "description": "URL to a file containing a list of baseurls for YUM repository", - "type": "string", - "error": "KCHREPOS0007E" - }, - "gpgcheck": { - "description": "Indicates if a GPG signature check on the packages gotten from repository should be performed.", - "type": "boolean", - "error": "KCHREPOS0009E" - }, - "gpgkey": { - "description": "URL pointing to the ASCII-armored GPG key file for the repository.", - "type": "string", - "error": "KCHREPOS0010E" - } - } - } - }, - "additionalProperties": false, - "error": "KCHAPI0001E" - }, "devices_get_list": { "type": "object", "properties": { diff --git a/src/wok/plugins/kimchi/Makefile.am b/src/wok/plugins/kimchi/Makefile.am index 82c4b19..8a55b23 100644 --- a/src/wok/plugins/kimchi/Makefile.am +++ b/src/wok/plugins/kimchi/Makefile.am @@ -100,7 +100,6 @@ install-deb: install cp -R $(top_srcdir)/contrib/DEBIAN $(DESTDIR)/ mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/vnc-tokens - mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/debugreports mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/screenshots mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/isos @@ -146,7 +145,6 @@ install-data-local: $(MKDIR_P) $(DESTDIR)$(kimchidir) $(INSTALL_DATA) API.json $(DESTDIR)$(kimchidir)/API.json mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/vnc-tokens - mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/debugreports mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/screenshots mkdir -p $(DESTDIR)/$(localstatedir)/lib/kimchi/isos diff --git a/src/wok/plugins/kimchi/control/host.py b/src/wok/plugins/kimchi/control/host.py index 32ab38f..e6bc662 100644 --- a/src/wok/plugins/kimchi/control/host.py +++ b/src/wok/plugins/kimchi/control/host.py @@ -17,10 +17,9 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -from wok.control.base import AsyncResource, Collection +from wok.control.base import Collection from wok.control.base import Resource, SimpleCollection from wok.control.utils import UrlSubNode -from wok.exception import NotFoundError from wok.plugins.kimchi.control.cpuinfo import CPUInfo @@ -32,15 +31,7 @@ class Host(Resource): self.role_key = 'host' self.admin_methods = ['GET', 'POST'] self.uri_fmt = '/host/%s' - self.reboot = self.generate_action_handler('reboot') - self.shutdown = self.generate_action_handler('shutdown') - self.stats = HostStats(self.model) - self.partitions = Partitions(self.model) self.devices = Devices(self.model) - self.packagesupdate = PackagesUpdate(self.model) - self.repositories = Repositories(self.model) - self.swupdate = self.generate_action_handler_task('swupdate') - self.swupdateprogress = SoftwareUpdateProgress(self.model) self.cpuinfo = CPUInfo(self.model) @property @@ -48,65 +39,6 @@ class Host(Resource): return self.info -class SoftwareUpdateProgress(AsyncResource): - def __init__(self, model, id=None): - super(SoftwareUpdateProgress, self).__init__(model, id) - self.role_key = 'host' - self.admin_methods = ['GET'] - - @property - def data(self): - return self.info - - -class HostStats(Resource): - def __init__(self, model, id=None): - super(HostStats, self).__init__(model, id) - self.role_key = 'host' - self.admin_methods = ['GET'] - self.history = HostStatsHistory(self.model) - - @property - def data(self): - return self.info - - -class HostStatsHistory(Resource): - @property - def data(self): - return self.info - - -class Partitions(Collection): - def __init__(self, model): - super(Partitions, self).__init__(model) - self.role_key = 'storage' - self.admin_methods = ['GET'] - self.resource = Partition - - # Defining get_resources in order to return list of partitions in UI - # sorted by their path - def _get_resources(self, flag_filter): - res_list = super(Partitions, self)._get_resources(flag_filter) - res_list = filter(lambda x: x.info['available'], res_list) - res_list.sort(key=lambda x: x.info['path']) - return res_list - - -class Partition(Resource): - def __init__(self, model, id): - self.role_key = 'storage' - self.admin_methods = ['GET'] - super(Partition, self).__init__(model, id) - - @property - def data(self): - if not self.info['available']: - raise NotFoundError("KCHPART0001E", {'name': self.info['name']}) - - return self.info - - class Devices(Collection): def __init__(self, model): super(Devices, self).__init__(model) @@ -127,44 +59,3 @@ class Device(Resource): @property def data(self): return self.info - - -class PackagesUpdate(Collection): - def __init__(self, model): - super(PackagesUpdate, self).__init__(model) - self.role_key = 'host' - self.admin_methods = ['GET'] - self.resource = PackageUpdate - - -class PackageUpdate(Resource): - def __init__(self, model, id=None): - super(PackageUpdate, self).__init__(model, id) - self.role_key = 'host' - self.admin_methods = ['GET'] - - @property - def data(self): - return self.info - - -class Repositories(Collection): - def __init__(self, model): - super(Repositories, self).__init__(model) - self.role_key = 'host' - self.admin_methods = ['GET', 'POST'] - self.resource = Repository - - -class Repository(Resource): - def __init__(self, model, id): - super(Repository, self).__init__(model, id) - self.role_key = 'host' - self.admin_methods = ['GET', 'PUT', 'POST', 'DELETE'] - self.uri_fmt = "/host/repositories/%s" - self.enable = self.generate_action_handler('enable') - self.disable = self.generate_action_handler('disable') - - @property - def data(self): - return self.info diff --git a/src/wok/plugins/kimchi/docs/API.md b/src/wok/plugins/kimchi/docs/API.md index e7f399b..280c8b2 100644 --- a/src/wok/plugins/kimchi/docs/API.md +++ b/src/wok/plugins/kimchi/docs/API.md @@ -782,88 +782,6 @@ Contains information about the OS distribution. *No actions defined* -#### Collection: Debug Reports - -**URI:** /plugins/kimchi/debugreports - -**Methods:** - -* **GET**: Retrieve a summarized list of all available Debug Reports -* **POST**: Create a new Debug Report. This POST method is different - from the other ones. The return resource is a task resource which - is identified by the url below - * task resource. * See Resource: Task * - -### Resource: Debug Report - -**URI:** /plugins/kimchi/debugreports/*:name* - -A Debug Report is an archive of logs and other information about the host that -is used to diagnose and debug problems. The exact format and contents are -specific to the low level collection tool being used. - -**Methods:** - -* **GET**: Retrieve the full description of Debug Report - * name: The debug report name used to identify the report - * uri: The URI path to download a debug report - * time: The time when the debug report is created - -* **PUT**: rename an existed debug report - * name: The new name for this debug report - -* **DELETE**: Remove the Debug Report - * name: The debug report name used to identify the report - -* **POST**: *See Debug Report Actions* - -**Actions (POST):** - -*No actions defined* - -### Sub-resource: Debug Report content - -**URI:** /plugins/kimchi/debugreports/*:name*/content - -It is the sub-resource of Debug Report and the client use it to get the real content -of the Debug Report file from the server - -* **GET**: Retrieve the content of a Debug Report file - -**Actions (POST):** - -*No actions defined* - -### Resource: Host - -**URI:** /plugins/kimchi/host -Contains information of host. - -**Methods:** - -* **GET**: Retrieve host static information - * memory: Total size of host physical memory - The unit is Bytes - * cpu_model: The model name of host CPU - * cpus: The number of online CPUs available on host - * os_distro: The OS distribution that runs on host - * os_version: The version of OS distribution - * os_codename: The code name of OS distribution - -* **POST**: *See Host Actions* - -**Actions (POST):** - -* reboot: Restart the host machine. - Only allowed if there is not vm running. -* shutdown: Power off the host machine. - Only allowed if there is not vm running. -* swupdate: Start the update of packages in background and return a Task resource - * task resource. * See Resource: Task * -* swupdateprogress: Read the package manager logfile in background and return a - Task resource. - * task resource. * See Resource: Task * - ### Resource: Users **URI:** /plugins/kimchi/users @@ -885,116 +803,6 @@ List of available groups. * **GET**: Retrieve list of available groups, only support 'pam' authentication. -### Resource: HostStats - -**URI:** /plugins/kimchi/host/stats - -Contains the host sample data. - -**Methods:** - -* **GET**: Retrieve host sample data - * cpu_utilization: A number between 0 and 100 which indicates the - percentage of CPU utilization. - * memory: memory statistics of host - * total: Total amount of memory. The unit is Bytes. - * free: The amount of memory left unused by the system. The unit is Bytes. - * buffers: The amount of memory used for file buffers. The unit is Bytes. - * cached: The amount of memory used as cache memory. The unit is Bytes. - * avail: The total amount of buffer, cache and free memory. The unit is Bytes. - * disk_read_rate: Expresses the total IO throughput for reads across - all disks (B/s). - * disk_write_rate: Expresses the total IO throughput for writes across - all disks (B/s). - * net_sent_rate: Expresses the total network throughput for writes across - all interfaces (B/s). - * net_recv_rate: Expresses the total network throughput for reads across - all interfaces (B/s). - -* **POST**: *See HostStats Actions* - -**Actions (POST):** - -*No actions defined* - -### Resource: HostStats - -**URI:** /plugins/kimchi/host/cpuinfo - -The cores and sockets of a hosts's CPU. Useful when sizing VMs to take -advantages of the perforamance benefits of SMT (Power) or Hyper-Threading (Intel). - -**Methods:** - -* **GET**: Retreives the sockets, cores, and threads values. - * threading_enabled: Whether CPU topology is supported on this system. - * sockets: The number of total sockets on a system. - * cores: The total number of cores per socket. - * threads_per_core: The threads per core. - -**Actions (PUT):** - -*No actions defined* - -**Actions (POST):** - -*No actions defined* - - -### Resource: HostStatsHistory - -**URI:** /plugins/kimchi/host/stats/history - -It is the sub-resource of Host Stats and the client uses it to get the host -stats history - -**Methods:** - -* **GET**: Retrieve host sample data history - * cpu_utilization: CPU utilization history - * memory: Memory statistics history - * total: Total amount of memory. The unit is Bytes. - * free: The amount of memory left unused by the system. The unit is Bytes. - * buffers: The amount of memory used for file buffers. The unit is Bytes. - * cached: The amount of memory used as cache memory. The unit is Bytes. - * avail: The total amount of buffer, cache and free memory. The unit is Bytes. - * disk_read_rate: IO throughput for reads history - * disk_write_rate: IO throughput for writes history - * net_sent_rate: Network throughput for writes history - * net_recv_rate: Network throughput for reads history - -* **POST**: *See HostStatsHistory Actions* - -**Actions (POST):** - -*No actions defined* - -### Collection: Partitions - -**URI:** /plugins/kimchi/host/partitions - -**Methods:** - -* **GET**: Retrieves a detailed list of all partitions of the host. - -### Resource: Partition - -**URI:** /plugins/kimchi/host/partitions/*:name* - -**Methods:** - -* **GET**: Retrieve the description of a single Partition: - * name: The name of the partition. Used to identify it in this API - * path: The device path of this partition. - * type: The type of the partition: - * part: a standard partition - * lvm: a partition that belongs to a lvm - * fstype: The file system type of the partition - * size: The total size of the partition, in bytes - * mountpoint: If the partition is mounted, represents the mountpoint. - Otherwise blank. - * available: false, if the partition is in use by system; true, otherwise. - ### Collection: Devices **URI:** /plugins/kimchi/host/devices @@ -1055,99 +863,6 @@ stats history * name: The name of the VM. * state: The power state of the VM. Could be "running" and "shutdown". - -### Collection: Host Packages Update - -**URI:** /plugins/kimchi/host/packagesupdate - -Contains the information and action of packages update in the host. - -**Methods:** - -* **GET**: Retrieves a list of all packages to be updated in the host: - -### Resource: Host Package Update - -**URI:** /plugins/kimchi/host/packagesupdate/*:name* - -Contains the information for a specific package to be updated. - -**Methods:** - -* **GET**: Retrieves a full description of a package: - * package_name: The name of the package to be updated - * arch: The architecture of the package - * version: The new version of the package - * repository: The repository name from where package will be downloaded - -### Collection: Host Repositories - -**URI:** /plugins/kimchi/host/repositories - -**Methods:** - -* **GET**: Retrieve a summarized list of all repositories available -* **POST**: Add a new repository - * baseurl: URL to the repodata directory when "is_mirror" is false. -Otherwise, it can be URL to the mirror system for YUM. Can be an -http://, ftp:// or file:// URL. - * repo_id *(optional)*: Unique YUM repository ID - * config: A dictionary that contains specific data according to repository - type. - * repo_name *(optional)*: YUM Repository name - * mirrorlist *(optional)*: Specifies a URL to a file containing a - list of baseurls for YUM repository - * dist: Distribution to DEB repository - * comps *(optional)*: List of components to DEB repository - -### Resource: Repository - -**URI:** /plugins/kimchi/host/repositories/*:repo-id* - -**Methods:** - -* **GET**: Retrieve the full description of a Repository - * repo_id: Unique repository name for each repository, one word. - * baseurl: URL to the repodata directory when "is_mirror" is false. -Otherwise, it can be URL to the mirror system for YUM. Can be an -http://, ftp:// or file:// URL. - * enabled: True, when repository is enabled; False, otherwise - * config: A dictionary that contains specific data according to repository - type. - * repo_name: Human-readable string describing the YUM repository. - * display_repo_name: The same name retrieve from repo_name with any - possible variable expanded. - * mirrorlist: Specifies a URL to a file containing a list of baseurls - for YUM repository - * gpgcheck: True, to enable GPG signature verification; False, otherwise. - * gpgkey: URL pointing to the ASCII-armored GPG key file for the YUM - repository. - * dist: Distribution to DEB repository - * comps: List of components to DEB repository - -* **DELETE**: Remove the Repository -* **POST**: *See Repository Actions* -* **PUT**: update the parameters of existing Repository - * repo_id: Unique repository name for each repository, one word. - * baseurl: URL to the repodata directory when "is_mirror" is false. -Otherwise, it can be URL to the mirror system for YUM. Can be an -http://, ftp:// or file:// URL. - * config: A dictionary that contains specific data according to repository - type. - * repo_name: Human-readable string describing the YUM repository. - * mirrorlist: Specifies a URL to a file containing a list of baseurls - for YUM repository - * gpgcheck: True, to enable GPG signature verification; False, otherwise. - * gpgkey: URL pointing to the ASCII-armored GPG key file for the YUM - repository. - * dist: Distribution to DEB repository - * comps: List of components to DEB repository - -**Actions (POST):** - -* enable: Enable the Repository as package source -* disable: Disable the Repository as package source - ### Collection: Peers **URI:** /plugins/kimchi/peers diff --git a/src/wok/plugins/kimchi/i18n.py b/src/wok/plugins/kimchi/i18n.py index 1f615df..8002dd1 100644 --- a/src/wok/plugins/kimchi/i18n.py +++ b/src/wok/plugins/kimchi/i18n.py @@ -32,9 +32,6 @@ messages = { "KCHDEVS0003E": _('"_passthrough_affected_by" should be a device name string'), "KCHDEVS0004E": _('"_available_only" should be "true" or "false"'), - "KCHDISKS0001E": _("Error while getting block devices. Details: %(err)s"), - "KCHDISKS0002E": _("Error while getting block device information for %(device)s."), - "KCHDL0001E": _("Unable to find distro file: %(filename)s"), "KCHDL0002E": _("Unable to parse distro file: %(filename)s. Make sure, it is a JSON file."), @@ -245,33 +242,13 @@ messages = { "KCHNET0021E": _("Failed to activate interface %(iface)s. Please check the physical link status."), "KCHNET0022E": _("Failed to start network %(name)s. Details: %(err)s"), - "KCHDR0001E": _("Debug report %(name)s does not exist"), - "KCHDR0002E": _("Debug report tool not found in system"), - "KCHDR0003E": _("Unable to create debug report %(name)s. Details: %(err)s."), - "KCHDR0004E": _("Can not find any debug report with the given name %(name)s"), - "KCHDR0005E": _("Unable to generate debug report %(name)s. Details: %(err)s"), - "KCHDR0006E": _("You should give a name for the debug report file."), - "KCHDR0007E": _("Debug report name must be a string. Only letters, digits, underscore ('_') and hyphen ('-') are allowed."), - "KCHDR0008E": _("The debug report with specified name \"%(name)s\" already exists. Please use another one."), - "KCHSR0001E": _("Storage server %(server)s was not used by Kimchi"), "KCHDISTRO0001E": _("Distro '%(name)s' does not exist"), - "KCHPART0001E": _("Partition %(name)s does not exist in the host"), - - "KCHHOST0001E": _("Unable to shutdown host machine as there are running virtual machines"), - "KCHHOST0002E": _("Unable to reboot host machine as there are running virtual machines"), "KCHHOST0003E": _("Node device '%(name)s' not found"), "KCHHOST0004E": _("Conflicting flag filters specified."), - "KCHPKGUPD0001E": _("No packages marked for update"), - "KCHPKGUPD0002E": _("Package %(name)s is not marked to be updated."), - "KCHPKGUPD0003E": _("Error while getting packages marked to be updated. Details: %(err)s"), - "KCHPKGUPD0004E": _("There is no compatible package manager for this system."), - "KCHPKGUPD0005E": _("There is a package manager instance running in the system."), - - "KCHUTILS0001E": _("Invalid Kimchi URI %(uri)s."), "KCHUTILS0003E": _("Unable to choose a virtual machine name"), "KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"), @@ -290,37 +267,6 @@ messages = { "KCHVMSTOR0017E": _("Only one of path or pool/volume can be specified to add a new virtual machine disk"), "KCHVMSTOR0018E": _("Volume chosen with format %(format)s does not fit in the storage type %(type)s"), - "KCHREPOS0001E": _("YUM Repository ID must be one word only string."), - "KCHREPOS0002E": _("Repository URL must be an http://, ftp:// or file:// URL."), - "KCHREPOS0003E": _("Repository configuration is a dictionary with specific values according to repository type."), - "KCHREPOS0004E": _("Distribution to DEB repository must be a string"), - "KCHREPOS0005E": _("Components to DEB repository must be listed in a array"), - "KCHREPOS0006E": _("Components to DEB repository must be a string"), - "KCHREPOS0007E": _("Mirror list to repository must be a string"), - "KCHREPOS0008E": _("YUM Repository name must be string."), - "KCHREPOS0009E": _("GPG check must be a boolean value."), - "KCHREPOS0010E": _("GPG key must be a URL pointing to the ASCII-armored file."), - "KCHREPOS0011E": _("Could not update repository %(repo_id)s."), - "KCHREPOS0012E": _("Repository %(repo_id)s does not exist."), - "KCHREPOS0013E": _("Specify repository base URL, mirror list or metalink in order to create or update a YUM repository."), - "KCHREPOS0014E": _("Repository management tool was not recognized for your system."), - "KCHREPOS0015E": _("Repository %(repo_id)s is already enabled."), - "KCHREPOS0016E": _("Repository %(repo_id)s is already disabled."), - "KCHREPOS0017E": _("Could not remove repository %(repo_id)s."), - "KCHREPOS0018E": _("Could not write repository configuration file %(repo_file)s"), - "KCHREPOS0019E": _("Specify repository distribution in order to create a DEB repository."), - "KCHREPOS0020E": _("Could not enable repository %(repo_id)s."), - "KCHREPOS0021E": _("Could not disable repository %(repo_id)s."), - "KCHREPOS0022E": _("YUM Repository ID already exists"), - "KCHREPOS0023E": _("YUM Repository name must be a string"), - "KCHREPOS0024E": _("Unable to list repositories. Details: '%(err)s'"), - "KCHREPOS0025E": _("Unable to retrieve repository information. Details: '%(err)s'"), - "KCHREPOS0026E": _("Unable to add repository. Details: '%(err)s'"), - "KCHREPOS0027E": _("Unable to remove repository. Details: '%(err)s'"), - "KCHREPOS0028E": _("Configuration items: '%(items)s' are not supported by repository manager"), - "KCHREPOS0029E": _("Repository metalink must be an http://, ftp:// or file:// URL."), - "KCHREPOS0030E": _("Cannot specify mirrorlist and metalink at the same time."), - "KCHSNAP0001E": _("Virtual machine '%(vm)s' must be stopped before creating a snapshot of it."), "KCHSNAP0002E": _("Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0003E": _("Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'."), diff --git a/src/wok/plugins/kimchi/kimchi.conf b/src/wok/plugins/kimchi/kimchi.conf index 1bf78e4..ebf346f 100644 --- a/src/wok/plugins/kimchi/kimchi.conf +++ b/src/wok/plugins/kimchi/kimchi.conf @@ -23,13 +23,6 @@ tools.staticdir.on = True tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/screenshots' tools.nocache.on = False -[/data/debugreports] -tools.staticdir.on = True -tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/debugreports' -tools.nocache.on = False -tools.wokauth.on = True -tools.staticdir.content_types = {'xz': 'application/x-xz'} - [/help] tools.staticdir.on = True tools.staticdir.dir = wok.config.PluginPaths('kimchi').ui_dir + '/pages/help' diff --git a/src/wok/plugins/kimchi/mockmodel.py b/src/wok/plugins/kimchi/mockmodel.py index 9ee5a15..1be477e 100644 --- a/src/wok/plugins/kimchi/mockmodel.py +++ b/src/wok/plugins/kimchi/mockmodel.py @@ -20,22 +20,19 @@ import libvirt import lxml.etree as ET import os -import random import time from lxml import objectify from lxml.builder import E from wok.exception import NotFoundError, OperationFailed from wok.objectstore import ObjectStore -from wok.utils import add_task, get_next_clone_name, wok_log +from wok.utils import add_task, get_next_clone_name from wok.xmlutils.utils import xml_item_update -from wok.plugins.kimchi import config from wok.plugins.kimchi import imageinfo from wok.plugins.kimchi import osinfo from wok.plugins.kimchi.model import cpuinfo from wok.plugins.kimchi.model import vmifaces -from wok.plugins.kimchi.model.debugreports import DebugReportsModel from wok.plugins.kimchi.model.host import DeviceModel from wok.plugins.kimchi.model.libvirtstoragepool import IscsiPoolDef from wok.plugins.kimchi.model.libvirtstoragepool import NetfsPoolDef @@ -77,10 +74,7 @@ class MockModel(Model): osinfo.defaults = dict(defaults) self._mock_devices = MockDevices() - self._mock_partitions = MockPartitions() self._mock_storagevolumes = MockStorageVolumes() - self._mock_swupdate = MockSoftwareUpdate() - self._mock_repositories = MockRepositories() cpuinfo.get_topo_capabilities = MockModel.get_topo_capabilities vmifaces.getDHCPLeases = MockModel.getDHCPLeases @@ -121,7 +115,6 @@ class MockModel(Model): StoragePoolModel._update_lvm_disks = self._update_lvm_disks StorageVolumesModel.get_list = self._mock_storagevolumes_get_list StorageVolumeModel.doUpload = self._mock_storagevolume_doUpload - DebugReportsModel._gen_debugreport_file = self._gen_debugreport_file LibvirtVMTemplate._get_volume_path = self._get_volume_path VMTemplate.get_iso_info = self._probe_image imageinfo.probe_image = self._probe_image @@ -129,8 +122,6 @@ class MockModel(Model): def reset(self): MockModel._mock_vms = {} MockModel._mock_snapshots = {} - self._mock_swupdate = MockSoftwareUpdate() - self._mock_repositories = MockRepositories() if hasattr(self, 'objstore'): self.objstore = ObjectStore(self.objstore_loc) @@ -260,22 +251,6 @@ class MockModel(Model): return MockModel._libvirt_get_vol_path(pool, vol) - def _gen_debugreport_file(self, name): - return add_task('/plugins/kimchi/debugreports/%s' % name, - self._create_log, self.objstore, name) - - def _create_log(self, cb, name): - path = config.get_debugreports_path() - tmpf = os.path.join(path, name + '.tmp') - realf = os.path.join(path, name + '.txt') - length = random.randint(1000, 10000) - with open(tmpf, 'w') as fd: - while length: - fd.write('I am logged') - length = length - 1 - os.rename(tmpf, realf) - cb("OK", True) - def _update_lvm_disks(self, pool_name, disks): conn = self.conn.get() pool = conn.storagePoolLookupByName(pool_name.encode('utf-8')) @@ -290,12 +265,6 @@ class MockModel(Model): conn.storagePoolDefineXML(ET.tostring(root), 0) - def _mock_host_shutdown(self, *name): - wok_log.info("The host system will be shutted down") - - def _mock_host_reboot(self, *name): - wok_log.info("The host system will be rebooted") - def _mock_storagevolumes_create(self, pool, params): vol_source = ['url', 'capacity'] index_list = list(i for i in range(len(vol_source)) @@ -343,12 +312,6 @@ class MockModel(Model): cb('', False) raise OperationFailed("KCHVOL0029E", {"err": e.message}) - def _mock_partitions_get_list(self): - return self._mock_partitions.partitions.keys() - - def _mock_partition_lookup(self, name): - return self._mock_partitions.partitions[name] - def _mock_devices_get_list(self, _cap=None, _passthrough=None, _passthrough_affected_by=None, _available_only=None): @@ -364,56 +327,6 @@ class MockModel(Model): def _mock_device_lookup(self, dev_name): return self._mock_devices.devices[dev_name] - def _mock_packagesupdate_get_list(self): - return self._mock_swupdate.pkgs.keys() - - def _mock_packageupdate_lookup(self, pkg_name): - return self._mock_swupdate.pkgs[pkg_name] - - def _mock_host_swupdate(self, args=None): - task_id = add_task('/plugins/kimchi/host/swupdate', - self._mock_swupdate.doUpdate, self.objstore) - return self.task_lookup(task_id) - - def _mock_repositories_get_list(self): - return self._mock_repositories.repos.keys() - - def _mock_repositories_create(self, params): - # Create a repo_id if not given by user. The repo_id will follow - # the format kimchi_repo_<integer>, where integer is the number of - # seconds since the Epoch (January 1st, 1970), in UTC. - repo_id = params.get('repo_id', None) - if repo_id is None: - repo_id = "kimchi_repo_%s" % str(int(time.time() * 1000)) - params.update({'repo_id': repo_id}) - - config = params.get('config', {}) - info = {'repo_id': repo_id, - 'baseurl': params['baseurl'], - 'enabled': True, - 'config': {'repo_name': config.get('repo_name', repo_id), - 'gpgkey': config.get('gpgkey', []), - 'gpgcheck': True, - 'mirrorlist': params.get('mirrorlist', '')}} - self._mock_repositories.repos[repo_id] = info - return repo_id - - def _mock_repository_lookup(self, repo_id): - return self._mock_repositories.repos[repo_id] - - def _mock_repository_delete(self, repo_id): - del self._mock_repositories.repos[repo_id] - - def _mock_repository_enable(self, repo_id): - self._mock_repositories.repos[repo_id]['enabled'] = True - - def _mock_repository_disable(self, repo_id): - self._mock_repositories.repos[repo_id]['enabled'] = False - - def _mock_repository_update(self, repo_id, params): - self._mock_repositories.repos[repo_id].update(params) - return repo_id - def _mock_vm_clone(self, name): new_name = get_next_clone_name(self.vms_get_list(), name) snapshots = MockModel._mock_snapshots.get(name, []) @@ -498,18 +411,6 @@ class MockStorageVolumes(object): 'isvalid': True}} -class MockPartitions(object): - def __init__(self): - self.partitions = {"vdx": {"available": True, "name": "vdx", - "fstype": "", "path": "/dev/vdx", - "mountpoint": "", "type": "disk", - "size": "2147483648"}, - "vdz": {"available": True, "name": "vdz", - "fstype": "", "path": "/dev/vdz", - "mountpoint": "", "type": "disk", - "size": "2147483648"}} - - class MockDevices(object): def __init__(self): self.devices = { @@ -587,51 +488,6 @@ class MockDevices(object): 'path': '/sys/devices/pci0000:00/0000:40:00.0/2'}} -class MockSoftwareUpdate(object): - def __init__(self): - self.pkgs = { - 'udevmountd': {'repository': 'openSUSE-13.1-Update', - 'version': '0.81.5-14.1', - 'arch': 'x86_64', - 'package_name': 'udevmountd'}, - 'sysconfig-network': {'repository': 'openSUSE-13.1-Extras', - 'version': '0.81.5-14.1', - 'arch': 'x86_64', - 'package_name': 'sysconfig-network'}, - 'libzypp': {'repository': 'openSUSE-13.1-Update', - 'version': '13.9.0-10.1', - 'arch': 'noarch', - 'package_name': 'libzypp'}} - self._num2update = 3 - - def doUpdate(self, cb, params): - msgs = [] - for pkg in self.pkgs.keys(): - msgs.append("Updating package %s" % pkg) - cb('\n'.join(msgs)) - time.sleep(1) - - time.sleep(2) - msgs.append("All packages updated") - cb('\n'.join(msgs), True) - - # After updating all packages any package should be listed to be - # updated, so reset self._packages - self.pkgs = {} - - -class MockRepositories(object): - def __init__(self): - self.repos = {"kimchi_repo_1392167832": - {"repo_id": "kimchi_repo_1392167832", - "enabled": True, - "baseurl": "http://www.fedora.org", - "config": {"repo_name": "kimchi_repo_1392167832", - "gpgkey": [], - "gpgcheck": True, - "mirrorlist": ""}}} - - class MockVMSnapshot(object): def __init__(self, name, params={}): self.name = name diff --git a/src/wok/plugins/kimchi/model/config.py b/src/wok/plugins/kimchi/model/config.py index 80b698b..e552edb 100644 --- a/src/wok/plugins/kimchi/model/config.py +++ b/src/wok/plugins/kimchi/model/config.py @@ -28,13 +28,10 @@ from wok.utils import run_command, wok_log from wok.plugins.kimchi.config import find_qemu_binary from wok.plugins.kimchi.distroloader import DistroLoader -from wok.plugins.kimchi.model.debugreports import DebugReportsModel from wok.plugins.kimchi.model.featuretests import FeatureTests from wok.plugins.kimchi.model.featuretests import FEATURETEST_POOL_NAME from wok.plugins.kimchi.model.featuretests import FEATURETEST_VM_NAME -from wok.plugins.kimchi.repositories import Repositories from wok.plugins.kimchi.screenshot import VMScreenshot -from wok.plugins.kimchi.swupdate import SoftwareUpdate from wok.plugins.kimchi.utils import check_url_path @@ -116,28 +113,10 @@ class CapabilitiesModel(object): return False def lookup(self, *ident): - report_tool = DebugReportsModel.get_system_report_tool() - try: - SoftwareUpdate() - except Exception: - update_tool = False - else: - update_tool = True - - try: - repo = Repositories() - except Exception: - repo_mngt_tool = None - else: - repo_mngt_tool = repo._pkg_mnger.TYPE - return {'libvirt_stream_protocols': self.libvirt_stream_protocols, 'qemu_spice': self._qemu_support_spice(), 'qemu_stream': self.qemu_stream, 'screenshot': VMScreenshot.get_stream_test_result(), - 'system_report_tool': bool(report_tool), - 'update_tool': update_tool, - 'repo_mngt_tool': repo_mngt_tool, 'federation': kconfig.get("server", "federation"), 'auth': kconfig.get("authentication", "method"), 'kernel_vfio': self.kernel_vfio, diff --git a/src/wok/plugins/kimchi/model/host.py b/src/wok/plugins/kimchi/model/host.py index 2db226d..54a0e71 100644 --- a/src/wok/plugins/kimchi/model/host.py +++ b/src/wok/plugins/kimchi/model/host.py @@ -18,28 +18,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import libvirt -import os -import platform import psutil -import time -from cherrypy.process.plugins import BackgroundTask -from collections import defaultdict from lxml import objectify -from wok.basemodel import Singleton -from wok.exception import InvalidOperation, InvalidParameter -from wok.exception import NotFoundError, OperationFailed -from wok.utils import add_task, wok_log +from wok.exception import InvalidParameter +from wok.exception import NotFoundError from wok.xmlutils.utils import xpath_get_text from wok.model.tasks import TaskModel -from wok.plugins.kimchi import disks -from wok.plugins.kimchi import netinfo from wok.plugins.kimchi.model import hostdev from wok.plugins.kimchi.model.config import CapabilitiesModel -from wok.plugins.kimchi.model.vms import DOM_STATE_MAP, VMModel, VMsModel -from wok.plugins.kimchi.repositories import Repositories -from wok.plugins.kimchi.swupdate import SoftwareUpdate +from wok.plugins.kimchi.model.vms import VMModel, VMsModel HOST_STATS_INTERVAL = 1 @@ -50,57 +39,7 @@ class HostModel(object): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) - self.host_info = self._get_host_info() - - def _get_ppc_cpu_info(self): - res = {} - with open('/proc/cpuinfo') as f: - for line in f.xreadlines(): - # Parse CPU, CPU's revision and CPU's clock information - for key in ['cpu', 'revision', 'clock']: - if key in line: - info = line.split(':')[1].strip() - if key == 'clock': - value = float(info.split('MHz')[0].strip()) / 1000 - else: - value = info.split('(')[0].strip() - res[key] = value - - # Power machines show, for each cpu/core, a block with - # all cpu information. Here we control the scan of the - # necessary information (1st block provides - # everything), skipping the function when find all - # information. - if len(res.keys()) == 3: - return "%(cpu)s (%(revision)s) @ %(clock)s GHz\ - " % res - - return "" - - def _get_host_info(self): - res = {} - if platform.machine().startswith('ppc'): - res['cpu_model'] = self._get_ppc_cpu_info() - else: - with open('/proc/cpuinfo') as f: - for line in f.xreadlines(): - if "model name" in line: - res['cpu_model'] = line.split(':')[1].strip() - break - - res['cpus'] = 0 - res['memory'] = 0L - - # Include IBM PowerKVM name to supported distro names - _sup_distros = platform._supported_dists + ('ibm_powerkvm',) - # 'fedora' '17' 'Beefy Miracle' - distro, version, codename = platform.linux_distribution( - supported_dists=_sup_distros) - res['os_distro'] = distro - res['os_version'] = version - res['os_codename'] = unicode(codename, "utf-8") - - return res + self.host_info = {} def lookup(self, *name): cpus = 0 @@ -128,200 +67,6 @@ class HostModel(object): self.host_info['memory'] = psutil.virtual_memory().total return self.host_info - def swupdate(self, *name): - try: - swupdate = SoftwareUpdate() - except: - raise OperationFailed('KCHPKGUPD0004E') - - pkgs = swupdate.getNumOfUpdates() - if pkgs == 0: - raise OperationFailed('KCHPKGUPD0001E') - - wok_log.debug('Host is going to be updated.') - taskid = add_task('/plugins/kimchi/host/swupdate', swupdate.doUpdate, - self.objstore, None) - return self.task.lookup(taskid) - - def shutdown(self, args=None): - # Check for running vms before shutdown - running_vms = self._get_vms_list_by_state('running') - if len(running_vms) > 0: - raise OperationFailed("KCHHOST0001E") - - wok_log.info('Host is going to shutdown.') - os.system('shutdown -h now') - - def reboot(self, args=None): - # Find running VMs - running_vms = self._get_vms_list_by_state('running') - if len(running_vms) > 0: - raise OperationFailed("KCHHOST0002E") - - wok_log.info('Host is going to reboot.') - os.system('reboot') - - def _get_vms_list_by_state(self, state): - conn = self.conn.get() - return [dom.name().decode('utf-8') - for dom in conn.listAllDomains(0) - if (DOM_STATE_MAP[dom.info()[0]]) == state] - - -class SoftwareUpdateProgressModel(object): - def __init__(self, **kargs): - self.task = TaskModel(**kargs) - self.objstore = kargs['objstore'] - - def lookup(self, *name): - try: - swupdate = SoftwareUpdate() - except: - raise OperationFailed('KCHPKGUPD0004E') - - taskid = add_task('/plugins/kimchi/host/swupdateprogress', - swupdate.tailUpdateLogs, self.objstore, None) - return self.task.lookup(taskid) - - -class HostStatsModel(object): - __metaclass__ = Singleton - - def __init__(self, **kargs): - self.host_stats = defaultdict(list) - self.host_stats_thread = BackgroundTask(HOST_STATS_INTERVAL, - self._update_host_stats) - self.host_stats_thread.start() - - def lookup(self, *name): - return {'cpu_utilization': self.host_stats['cpu_utilization'][-1], - 'memory': self.host_stats['memory'][-1], - 'disk_read_rate': self.host_stats['disk_read_rate'][-1], - 'disk_write_rate': self.host_stats['disk_write_rate'][-1], - 'net_recv_rate': self.host_stats['net_recv_rate'][-1], - 'net_sent_rate': self.host_stats['net_sent_rate'][-1]} - - def _update_host_stats(self): - preTimeStamp = self.host_stats['timestamp'] - timestamp = time.time() - # FIXME when we upgrade psutil, we can get uptime by psutil.uptime - # we get uptime by float(open("/proc/uptime").readline().split()[0]) - # and calculate the first io_rate after the OS started. - with open("/proc/uptime") as time_f: - seconds = (timestamp - preTimeStamp if preTimeStamp else - float(time_f.readline().split()[0])) - - self.host_stats['timestamp'] = timestamp - self._get_host_disk_io_rate(seconds) - self._get_host_network_io_rate(seconds) - - self._get_percentage_host_cpu_usage() - self._get_host_memory_stats() - - # store only 60 stats (1 min) - for key, value in self.host_stats.iteritems(): - if isinstance(value, list): - if len(value) == 60: - self.host_stats[key] = value[10:] - - def _get_percentage_host_cpu_usage(self): - # This is cpu usage producer. This producer will calculate the usage - # at an interval of HOST_STATS_INTERVAL. - # The psutil.cpu_percent works as non blocking. - # psutil.cpu_percent maintains a cpu time sample. - # It will update the cpu time sample when it is called. - # So only this producer can call psutil.cpu_percent in kimchi. - self.host_stats['cpu_utilization'].append(psutil.cpu_percent(None)) - - def _get_host_memory_stats(self): - virt_mem = psutil.virtual_memory() - # available: - # the actual amount of available memory that can be given - # instantly to processes that request more memory in bytes; this - # is calculated by summing different memory values depending on - # the platform (e.g. free + buffers + cached on Linux) - memory_stats = {'total': virt_mem.total, - 'free': virt_mem.free, - 'cached': virt_mem.cached, - 'buffers': virt_mem.buffers, - 'avail': virt_mem.available} - self.host_stats['memory'].append(memory_stats) - - def _get_host_disk_io_rate(self, seconds): - disk_read_bytes = self.host_stats['disk_read_bytes'] - disk_write_bytes = self.host_stats['disk_write_bytes'] - prev_read_bytes = disk_read_bytes[-1] if disk_read_bytes else 0 - prev_write_bytes = disk_write_bytes[-1] if disk_write_bytes else 0 - - disk_io = psutil.disk_io_counters(False) - read_bytes = disk_io.read_bytes - write_bytes = disk_io.write_bytes - - rd_rate = int(float(read_bytes - prev_read_bytes) / seconds + 0.5) - wr_rate = int(float(write_bytes - prev_write_bytes) / seconds + 0.5) - - self.host_stats['disk_read_rate'].append(rd_rate) - self.host_stats['disk_write_rate'].append(wr_rate) - self.host_stats['disk_read_bytes'].append(read_bytes) - self.host_stats['disk_write_bytes'].append(write_bytes) - - def _get_host_network_io_rate(self, seconds): - net_recv_bytes = self.host_stats['net_recv_bytes'] - net_sent_bytes = self.host_stats['net_sent_bytes'] - prev_recv_bytes = net_recv_bytes[-1] if net_recv_bytes else 0 - prev_sent_bytes = net_sent_bytes[-1] if net_sent_bytes else 0 - - net_ios = None - if hasattr(psutil, 'net_io_counters'): - net_ios = psutil.net_io_counters(True) - elif hasattr(psutil, 'network_io_counters'): - net_ios = psutil.network_io_counters(True) - - recv_bytes = 0 - sent_bytes = 0 - for key in set(netinfo.nics() + - netinfo.wlans()) & set(net_ios.iterkeys()): - recv_bytes = recv_bytes + net_ios[key].bytes_recv - sent_bytes = sent_bytes + net_ios[key].bytes_sent - - rx_rate = int(float(recv_bytes - prev_recv_bytes) / seconds + 0.5) - tx_rate = int(float(sent_bytes - prev_sent_bytes) / seconds + 0.5) - - self.host_stats['net_recv_rate'].append(rx_rate) - self.host_stats['net_sent_rate'].append(tx_rate) - self.host_stats['net_recv_bytes'].append(recv_bytes) - self.host_stats['net_sent_bytes'].append(sent_bytes) - - -class HostStatsHistoryModel(object): - def __init__(self, **kargs): - self.history = HostStatsModel(**kargs) - - def lookup(self, *name): - return {'cpu_utilization': self.history.host_stats['cpu_utilization'], - 'memory': self.history.host_stats['memory'], - 'disk_read_rate': self.history.host_stats['disk_read_rate'], - 'disk_write_rate': self.history.host_stats['disk_write_rate'], - 'net_recv_rate': self.history.host_stats['net_recv_rate'], - 'net_sent_rate': self.history.host_stats['net_sent_rate']} - - -class PartitionsModel(object): - def __init__(self, **kargs): - pass - - def get_list(self): - result = disks.get_partitions_names() - return result - - -class PartitionModel(object): - def __init__(self, **kargs): - pass - - def lookup(self, name): - return disks.get_partition_details(name) - class DevicesModel(object): def __init__(self, **kargs): @@ -517,88 +262,3 @@ class DeviceModel(object): if ebus == ibus and edevice == idevice: return usb_info['name'] return unknown_dev - - -class PackagesUpdateModel(object): - def __init__(self, **kargs): - try: - self.host_swupdate = SoftwareUpdate() - except: - self.host_swupdate = None - - def get_list(self): - if self.host_swupdate is None: - raise OperationFailed('KCHPKGUPD0004E') - - return self.host_swupdate.getUpdates() - - -class PackageUpdateModel(object): - def __init__(self, **kargs): - pass - - def lookup(self, name): - try: - swupdate = SoftwareUpdate() - except Exception: - raise OperationFailed('KCHPKGUPD0004E') - - return swupdate.getUpdate(name) - - -class RepositoriesModel(object): - def __init__(self, **kargs): - try: - self.host_repositories = Repositories() - except: - self.host_repositories = None - - def get_list(self): - if self.host_repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return sorted(self.host_repositories.getRepositories()) - - def create(self, params): - if self.host_repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self.host_repositories.addRepository(params) - - -class RepositoryModel(object): - def __init__(self, **kargs): - try: - self._repositories = Repositories() - except: - self._repositories = None - - def lookup(self, repo_id): - if self._repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self._repositories.getRepository(repo_id) - - def enable(self, repo_id): - if self._repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self._repositories.enableRepository(repo_id) - - def disable(self, repo_id): - if self._repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self._repositories.disableRepository(repo_id) - - def update(self, repo_id, params): - if self._repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self._repositories.updateRepository(repo_id, params) - - def delete(self, repo_id): - if self._repositories is None: - raise InvalidOperation('KCHREPOS0014E') - - return self._repositories.removeRepository(repo_id) diff --git a/src/wok/plugins/kimchi/root.py b/src/wok/plugins/kimchi/root.py index c59f859..44452b4 100644 --- a/src/wok/plugins/kimchi/root.py +++ b/src/wok/plugins/kimchi/root.py @@ -56,7 +56,6 @@ class KimchiRoot(WokRoot): make_dirs = [ os.path.dirname(os.path.abspath(config.get_object_store())), os.path.abspath(config.get_distros_store()), - os.path.abspath(config.get_debugreports_path()), os.path.abspath(config.get_screenshot_path()) ] for directory in make_dirs: diff --git a/src/wok/plugins/kimchi/tests/test_authorization.py b/src/wok/plugins/kimchi/tests/test_authorization.py index 87d68ab..fda86a3 100644 --- a/src/wok/plugins/kimchi/tests/test_authorization.py +++ b/src/wok/plugins/kimchi/tests/test_authorization.py @@ -77,12 +77,6 @@ class AuthorizationTests(unittest.TestCase): resp = self.request('/plugins/kimchi/host/shutdown', '{}', 'POST') self.assertEquals(403, resp.status) - # Non-root users can not get or debug reports - resp = self.request('/plugins/kimchi/debugreports', '{}', 'GET') - self.assertEquals(403, resp.status) - resp = self.request('/plugins/kimchi/debugreports', '{}', 'POST') - self.assertEquals(403, resp.status) - # Non-root users can not create or delete network (only get) resp = self.request('/plugins/kimchi/networks', '{}', 'GET') self.assertEquals(200, resp.status) diff --git a/src/wok/plugins/kimchi/tests/test_config.py.in b/src/wok/plugins/kimchi/tests/test_config.py.in index fb23b5c..171dfbb 100644 --- a/src/wok/plugins/kimchi/tests/test_config.py.in +++ b/src/wok/plugins/kimchi/tests/test_config.py.in @@ -23,7 +23,6 @@ from cherrypy.lib.reprconf import Parser from wok.config import CACHEEXPIRES, SESSIONSTIMEOUT from wok.config import Paths, PluginPaths -from wok.plugins.kimchi.config import get_debugreports_path from wok.plugins.kimchi.config import get_screenshot_path from wok.plugins.kimchi.config import KimchiConfig, KimchiPaths @@ -158,13 +157,6 @@ class ConfigTests(unittest.TestCase): 'tools.staticfile.filename': '%s/ui/config/tab-ext.xml' % pluginPrefix, }, - '/data/debugreports': { - 'tools.wokauth.on': True, - 'tools.nocache.on': False, - 'tools.staticdir.dir': get_debugreports_path(), - 'tools.staticdir.content_types': {'xz': 'application/x-xz'}, - 'tools.staticdir.on': True - } } kimchi_config = Parser().dict_from_file(KimchiPaths().conf_file) diff --git a/src/wok/plugins/kimchi/tests/test_host.py b/src/wok/plugins/kimchi/tests/test_host.py index 2940f48..86cf5d0 100644 --- a/src/wok/plugins/kimchi/tests/test_host.py +++ b/src/wok/plugins/kimchi/tests/test_host.py @@ -20,16 +20,13 @@ import json import os -import platform -import psutil import tempfile -import time import unittest from functools import partial from wok.plugins.kimchi.mockmodel import MockModel -from utils import get_free_port, patch_auth, request, run_server, wait_task +from utils import get_free_port, patch_auth, request, run_server test_server = None @@ -62,98 +59,6 @@ class HostTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) - def test_hostinfo(self): - resp = self.request('/plugins/kimchi/host').read() - info = json.loads(resp) - keys = ['os_distro', 'os_version', 'os_codename', 'cpu_model', - 'memory', 'cpus'] - self.assertEquals(sorted(keys), sorted(info.keys())) - - distro, version, codename = platform.linux_distribution() - self.assertEquals(distro, info['os_distro']) - self.assertEquals(version, info['os_version']) - self.assertEquals(unicode(codename, "utf-8"), info['os_codename']) - self.assertEquals(psutil.TOTAL_PHYMEM, info['memory']) - - def test_hoststats(self): - time.sleep(1) - stats_keys = ['cpu_utilization', 'memory', 'disk_read_rate', - 'disk_write_rate', 'net_recv_rate', 'net_sent_rate'] - resp = self.request('/plugins/kimchi/host/stats').read() - stats = json.loads(resp) - self.assertEquals(sorted(stats_keys), sorted(stats.keys())) - - cpu_utilization = stats['cpu_utilization'] - self.assertIsInstance(cpu_utilization, float) - self.assertGreaterEqual(cpu_utilization, 0.0) - self.assertTrue(cpu_utilization <= 100.0) - - memory_stats = stats['memory'] - self.assertIn('total', memory_stats) - self.assertIn('free', memory_stats) - self.assertIn('cached', memory_stats) - self.assertIn('buffers', memory_stats) - self.assertIn('avail', memory_stats) - - resp = self.request('/plugins/kimchi/host/stats/history').read() - history = json.loads(resp) - self.assertEquals(sorted(stats_keys), sorted(history.keys())) - - def test_host_actions(self): - def _task_lookup(taskid): - return json.loads( - self.request('/plugins/kimchi/tasks/%s' % taskid).read() - ) - - resp = self.request('/plugins/kimchi/host/shutdown', '{}', 'POST') - self.assertEquals(200, resp.status) - resp = self.request('/plugins/kimchi/host/reboot', '{}', 'POST') - self.assertEquals(200, resp.status) - - # Test system update - resp = self.request('/plugins/kimchi/host/packagesupdate', None, 'GET') - pkgs = json.loads(resp.read()) - self.assertEquals(3, len(pkgs)) - - pkg_keys = ['package_name', 'repository', 'arch', 'version'] - for p in pkgs: - name = p['package_name'] - resp = self.request('/plugins/kimchi/host/packagesupdate/' + name, - None, 'GET') - info = json.loads(resp.read()) - self.assertEquals(sorted(pkg_keys), sorted(info.keys())) - - resp = self.request('/plugins/kimchi/host/swupdate', '{}', 'POST') - task = json.loads(resp.read()) - task_params = [u'id', u'message', u'status', u'target_uri'] - self.assertEquals(sorted(task_params), sorted(task.keys())) - - resp = self.request('/plugins/kimchi/tasks/' + task[u'id'], None, - 'GET') - task_info = json.loads(resp.read()) - self.assertEquals(task_info['status'], 'running') - wait_task(_task_lookup, task_info['id']) - resp = self.request('/plugins/kimchi/tasks/' + task[u'id'], None, - 'GET') - task_info = json.loads(resp.read()) - self.assertEquals(task_info['status'], 'finished') - self.assertIn(u'All packages updated', task_info['message']) - pkgs = model.packagesupdate_get_list() - self.assertEquals(0, len(pkgs)) - - def test_host_partitions(self): - resp = self.request('/plugins/kimchi/host/partitions') - self.assertEquals(200, resp.status) - partitions = json.loads(resp.read()) - - keys = ['name', 'path', 'type', 'fstype', 'size', 'mountpoint', - 'available'] - for item in partitions: - resp = self.request('/plugins/kimchi/host/partitions/%s' % - item['name']) - info = json.loads(resp.read()) - self.assertEquals(sorted(info.keys()), sorted(keys)) - def test_host_devices(self): def asset_devices_type(devices, dev_type): for dev in devices: diff --git a/src/wok/plugins/kimchi/tests/test_model.py b/src/wok/plugins/kimchi/tests/test_model.py index 55117cf..a2c7105 100644 --- a/src/wok/plugins/kimchi/tests/test_model.py +++ b/src/wok/plugins/kimchi/tests/test_model.py @@ -25,7 +25,6 @@ import re import shutil import time import unittest -import uuid import wok.objectstore from wok.basemodel import Singleton @@ -1065,54 +1064,6 @@ class ModelTests(unittest.TestCase): self.assertTrue('kimchi-vm' in vms) - @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') - def test_debug_reports(self): - inst = model.Model('test:///default', - objstore_loc=self.tmp_store) - - if not inst.capabilities_lookup()['system_report_tool']: - raise unittest.SkipTest("Without debug report tool") - - try: - timeout = int(os.environ['TEST_REPORT_TIMEOUT']) - except (ValueError, KeyError): - timeout = 120 - - namePrefix = 'unitTestReport' - # sosreport always deletes unsual letters like '-' and '_' in the - # generated report file name. - uuidstr = str(uuid.uuid4()).translate(None, "-_") - reportName = namePrefix + uuidstr - try: - inst.debugreport_delete(namePrefix + '*') - except NotFoundError: - pass - with RollbackContext() as rollback: - report_list = inst.debugreports_get_list() - self.assertFalse(reportName in report_list) - try: - tmp_name = reportName + "_1" - task = inst.debugreports_create({'name': reportName}) - rollback.prependDefer(inst.debugreport_delete, tmp_name) - taskid = task['id'] - inst.task_wait(taskid, timeout) - self.assertEquals('finished', - inst.task_lookup(taskid)['status'], - "It is not necessary an error. " - "You may need to increase the " - "timeout number by " - "TEST_REPORT_TIMEOUT=200 " - "./run_tests.sh test_model") - report_list = inst.debugreports_get_list() - self.assertTrue(reportName in report_list) - name = inst.debugreport_update(reportName, {'name': tmp_name}) - self.assertEquals(name, tmp_name) - report_list = inst.debugreports_get_list() - self.assertTrue(tmp_name in report_list) - except OperationFailed, e: - if 'debugreport tool not found' not in e.message: - raise e - def test_get_distros(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) @@ -1151,194 +1102,6 @@ class ModelTests(unittest.TestCase): volumes = inst.storagevolumes_get_list(args['name']) self.assertEquals(len(volumes), 2) - def test_repository_create(self): - inst = model.Model('test:///default', - objstore_loc=self.tmp_store) - - yum_repos = [{'repo_id': 'fedora-fake', - 'baseurl': 'http://www.fedora.org'}, - {'repo_id': 'fedora-updates-fake', - 'config': - {'mirrorlist': 'http://www.fedoraproject.org'}}] - - deb_repos = [{'baseurl': 'http://archive.ubuntu.com/ubuntu/', - 'config': {'dist': 'quantal'}}, - {'baseurl': 'http://archive.ubuntu.com/ubuntu/', - 'config': {'dist': 'quantal', 'comps': ['main']}}] - - yum_invalid_repos = [] - deb_invalid_repos = [] - - for url in invalid_repository_urls: - wrong_baseurl = {'repo_id': 'wrong-id', 'baseurl': url} - wrong_mirrorlist = {'repo_id': 'wrong-id', - 'baseurl': 'www.example.com', - 'config': {'mirrorlist': url}} - wrong_config_item = { - 'repo_id': 'wrong-id', - 'baseurl': 'www.example.com', - 'config': { - 'gpgkey': 'file:///tmp/KEY-fedora-updates-fake-19'}} - - yum_invalid_repos.append(wrong_baseurl) - yum_invalid_repos.append(wrong_mirrorlist) - yum_invalid_repos.append(wrong_config_item) - - wrong_baseurl['config'] = {'dist': 'tasty'} - wrong_config = {'baseurl': deb_repos[0]['baseurl'], - 'config': { - 'unsupported_item': "a_unsupported_item"}} - deb_invalid_repos.append(wrong_baseurl) - deb_invalid_repos.append(wrong_config) - - repo_type = inst.capabilities_lookup()['repo_mngt_tool'] - if repo_type == 'yum': - test_repos = yum_repos - invalid_repos = yum_invalid_repos - elif repo_type == 'deb': - test_repos = deb_repos - invalid_repos = deb_invalid_repos - else: - # repository management tool was not recognized by Kimchi - # skip test case - return - - # create repositories with invalid data - for repo in invalid_repos: - self.assertRaises(InvalidParameter, inst.repositories_create, repo) - - for repo in test_repos: - system_host_repos = len(inst.repositories_get_list()) - repo_id = inst.repositories_create(repo) - host_repos = inst.repositories_get_list() - self.assertEquals(system_host_repos + 1, len(host_repos)) - - repo_info = inst.repository_lookup(repo_id) - self.assertEquals(repo_id, repo_info['repo_id']) - self.assertEquals(True, repo_info.get('enabled')) - self.assertEquals(repo.get('baseurl', ''), - repo_info.get('baseurl')) - - original_config = repo.get('config', {}) - config_info = repo_info.get('config', {}) - - if repo_type == 'yum': - self.assertEquals(original_config.get('mirrorlist', ''), - config_info.get('mirrorlist', '')) - self.assertEquals(True, config_info['gpgcheck']) - else: - self.assertEquals(original_config['dist'], config_info['dist']) - self.assertEquals(original_config.get('comps', []), - config_info.get('comps', [])) - - inst.repository_delete(repo_id) - self.assertRaises(NotFoundError, inst.repository_lookup, repo_id) - - self.assertRaises(NotFoundError, inst.repository_lookup, 'google') - - def test_repository_update(self): - inst = model.Model('test:///default', - objstore_loc=self.tmp_store) - - yum_repo = {'repo_id': 'fedora-fake', - 'baseurl': 'http://www.fedora.org'} - yum_new_repo = {'baseurl': 'http://www.fedoraproject.org'} - - deb_repo = {'baseurl': 'http://archive.ubuntu.com/ubuntu/', - 'config': {'dist': 'quantal'}} - deb_new_repo = {'baseurl': 'http://br.archive.canonical.com/ubuntu/', - 'config': {'dist': 'utopic'}} - - yum_invalid_repos = [] - deb_invalid_repos = [] - - for url in invalid_repository_urls: - wrong_baseurl = {'baseurl': url} - wrong_mirrorlist = {'baseurl': 'www.example.com', - 'config': {'mirrorlist': url}} - - yum_invalid_repos.append(wrong_baseurl) - yum_invalid_repos.append(wrong_mirrorlist) - - wrong_baseurl['config'] = {'dist': 'tasty'} - deb_invalid_repos.append(wrong_baseurl) - - repo_type = inst.capabilities_lookup()['repo_mngt_tool'] - if repo_type == 'yum': - repo = yum_repo - new_repo = yum_new_repo - invalid_repos = yum_invalid_repos - elif repo_type == 'deb': - repo = deb_repo - new_repo = deb_new_repo - invalid_repos = deb_invalid_repos - else: - # repository management tool was not recognized by Kimchi - # skip test case - return - - system_host_repos = len(inst.repositories_get_list()) - - with RollbackContext() as rollback: - repo_id = inst.repositories_create(repo) - rollback.prependDefer(inst.repository_delete, repo_id) - - host_repos = inst.repositories_get_list() - self.assertEquals(system_host_repos + 1, len(host_repos)) - - # update repositories with invalid data - for tmp_repo in invalid_repos: - self.assertRaises(InvalidParameter, inst.repository_update, - repo_id, tmp_repo) - - new_repo_id = inst.repository_update(repo_id, new_repo) - repo_info = inst.repository_lookup(new_repo_id) - - self.assertEquals(new_repo_id, repo_info['repo_id']) - self.assertEquals(new_repo['baseurl'], repo_info['baseurl']) - self.assertEquals(True, repo_info['enabled']) - inst.repository_update(new_repo_id, repo) - - def test_repository_disable_enable(self): - inst = model.Model('test:///default', - objstore_loc=self.tmp_store) - - yum_repo = {'repo_id': 'fedora-fake', - 'baseurl': 'http://www.fedora.org'} - deb_repo = {'baseurl': 'http://archive.ubuntu.com/ubuntu/', - 'config': {'dist': 'quantal'}} - - repo_type = inst.capabilities_lookup()['repo_mngt_tool'] - if repo_type == 'yum': - repo = yum_repo - elif repo_type == 'deb': - repo = deb_repo - else: - # repository management tool was not recognized by Kimchi - # skip test case - return - - system_host_repos = len(inst.repositories_get_list()) - - repo_id = inst.repositories_create(repo) - - host_repos = inst.repositories_get_list() - self.assertEquals(system_host_repos + 1, len(host_repos)) - - repo_info = inst.repository_lookup(repo_id) - self.assertEquals(True, repo_info['enabled']) - - inst.repository_disable(repo_id) - repo_info = inst.repository_lookup(repo_id) - self.assertEquals(False, repo_info['enabled']) - - inst.repository_enable(repo_id) - repo_info = inst.repository_lookup(repo_id) - self.assertEquals(True, repo_info['enabled']) - - # remove files creates - inst.repository_delete(repo_id) - class BaseModelTests(unittest.TestCase): class FoosModel(object): diff --git a/src/wok/plugins/kimchi/tests/test_rest.py b/src/wok/plugins/kimchi/tests/test_rest.py index e1a2f54..0c853f8 100644 --- a/src/wok/plugins/kimchi/tests/test_rest.py +++ b/src/wok/plugins/kimchi/tests/test_rest.py @@ -1266,60 +1266,6 @@ class RestTests(unittest.TestCase): # Distro not found error self.assertIn('KCHDISTRO0001E', distro.get('reason')) - def test_debugreports(self): - resp = request(host, ssl_port, '/plugins/kimchi/debugreports') - self.assertEquals(200, resp.status) - - def _report_delete(self, name): - request(host, ssl_port, '/plugins/kimchi/debugreports/%s' % name, '{}', - 'DELETE') - - def test_create_debugreport(self): - req = json.dumps({'name': 'report1'}) - with RollbackContext() as rollback: - resp = request(host, ssl_port, '/plugins/kimchi/debugreports', req, - 'POST') - self.assertEquals(202, resp.status) - task = json.loads(resp.read()) - # make sure the debugreport doesn't exist until the - # the task is finished - wait_task(self._task_lookup, task['id']) - rollback.prependDefer(self._report_delete, 'report2') - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1') - debugreport = json.loads(resp.read()) - self.assertEquals("report1", debugreport['name']) - self.assertEquals(200, resp.status) - req = json.dumps({'name': 'report2'}) - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1', req, 'PUT') - self.assertEquals(303, resp.status) - - def test_debugreport_download(self): - req = json.dumps({'name': 'report1'}) - with RollbackContext() as rollback: - resp = request(host, ssl_port, '/plugins/kimchi/debugreports', req, - 'POST') - self.assertEquals(202, resp.status) - task = json.loads(resp.read()) - # make sure the debugreport doesn't exist until the - # the task is finished - wait_task(self._task_lookup, task['id'], 20) - rollback.prependDefer(self._report_delete, 'report1') - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1') - debugreport = json.loads(resp.read()) - self.assertEquals("report1", debugreport['name']) - self.assertEquals(200, resp.status) - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1/content') - self.assertEquals(200, resp.status) - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1') - debugre = json.loads(resp.read()) - resp = request(host, ssl_port, debugre['uri']) - self.assertEquals(200, resp.status) - def test_repositories(self): def verify_repo(t, res): for field in ('repo_id', 'enabled', 'baseurl', 'config'): diff --git a/src/wok/plugins/kimchi/ui/config/tab-ext.xml b/src/wok/plugins/kimchi/ui/config/tab-ext.xml index ee88c88..48ec9ec 100644 --- a/src/wok/plugins/kimchi/ui/config/tab-ext.xml +++ b/src/wok/plugins/kimchi/ui/config/tab-ext.xml @@ -2,13 +2,6 @@ <tabs-ext> <tab> <access role="admin" mode="admin"/> - <access role="user" mode="none"/> - - <title>Host</title> - <path>plugins/kimchi/host.html</path> - </tab> - <tab> - <access role="admin" mode="admin"/> <access role="user" mode="byInstance"/> <title>Guests</title> diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.api.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.api.js index bb3a53d..6ffa0df 100644 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.api.js +++ b/src/wok/plugins/kimchi/ui/js/src/kimchi.api.js @@ -55,52 +55,6 @@ var kimchi = { }, /** - * Get the host static information. - */ - getHost: function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host', - type : 'GET', - resend: true, - contentType : 'application/json', - dataType : 'json', - success : suc, - error: err - }); - }, - - /** - * Get the dynamic host stats (usually used for monitoring). - */ - getHostStats : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host/stats', - type : 'GET', - contentType : 'application/json', - headers: {'Wok-Robot': 'wok-robot'}, - dataType : 'json', - success : suc, - error: err - }); - }, - - /** - * Get the historic host stats. - */ - getHostStatsHistory : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host/stats/history', - type : 'GET', - resend: true, - contentType : 'application/json', - headers: {'Wok-Robot': 'wok-robot'}, - dataType : 'json', - success : suc, - error: err - }); - }, - - /** * * Create a new Virtual Machine. Usage: kimchi.createVM({ name: 'MyUbuntu', * template: '/templates/ubuntu_base' }, creationSuc, creationErr); @@ -638,113 +592,6 @@ var kimchi = { }); }, - listReports : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/debugreports', - type : 'GET', - contentType : 'application/json', - dataType : 'json', - resend: true, - success : suc, - error : err - }); - }, - - trackTask : function(taskID, suc, err, progress) { - var onTaskResponse = function(result) { - var taskStatus = result['status']; - switch(taskStatus) { - case 'running': - progress && progress(result); - setTimeout(function() { - kimchi.trackTask(taskID, suc, err, progress); - }, 2000); - break; - case 'finished': - suc && suc(result); - break; - case 'failed': - err && err(result); - break; - default: - break; - } - }; - - kimchi.getTask(taskID, onTaskResponse, err); - if(kimchi.trackingTasks.indexOf(taskID) < 0) - kimchi.trackingTasks.push(taskID); - }, - - createReport: function(settings, suc, err, progress) { - var onResponse = function(data) { - taskID = data['id']; - kimchi.trackTask(taskID, suc, err, progress); - }; - - wok.requestJSON({ - url : 'plugins/kimchi/debugreports', - type : "POST", - contentType : "application/json", - data : JSON.stringify(settings), - dataType : "json", - success : onResponse, - error : err - }); - }, - - renameReport : function(name, settings, suc, err) { - $.ajax({ - url : "plugins/kimchi/debugreports/" + encodeURIComponent(name), - type : 'PUT', - contentType : 'application/json', - data : JSON.stringify(settings), - dataType : 'json', - success: suc, - error: err - }); - }, - - deleteReport: function(settings, suc, err) { - var reportName = encodeURIComponent(settings['name']); - wok.requestJSON({ - url : 'plugins/kimchi/debugreports/' + reportName, - type : 'DELETE', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - - downloadReport: function(settings, suc, err) { - window.open(settings['file']); - }, - - shutdown: function(settings, suc, err) { - var reboot = settings && settings['reboot'] === true; - var url = 'plugins/kimchi/host/' + (reboot ? 'reboot' : 'shutdown'); - wok.requestJSON({ - url : url, - type : 'POST', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - - listHostPartitions : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host/partitions', - type : 'GET', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - getStorageServers: function(type, suc, err) { var url = 'plugins/kimchi/storageservers?_target_type=' + type; wok.requestJSON({ @@ -872,170 +719,6 @@ var kimchi = { }); }, - listSoftwareUpdates : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host/packagesupdate', - type : 'GET', - contentType : 'application/json', - dataType : 'json', - resend: true, - success : suc, - error : err - }); - }, - - softwareUpdateProgress : function(suc, err, progress) { - var taskID = -1; - var onResponse = function(data) { - taskID = data['id']; - trackTask(); - }; - - var trackTask = function() { - kimchi.getTask(taskID, onTaskResponse, err); - }; - - var onTaskResponse = function(result) { - var taskStatus = result['status']; - switch(taskStatus) { - case 'running': - progress && progress(result); - setTimeout(function() { - trackTask(); - }, 1000); - break; - case 'finished': - case 'failed': - suc(result); - break; - default: - break; - } - }; - - wok.requestJSON({ - url : 'plugins/kimchi/host/swupdateprogress', - type : "GET", - contentType : "application/json", - dataType : "json", - success : onResponse, - error : err - }); - }, - - updateSoftware : function(suc, err, progress) { - var taskID = -1; - var onResponse = function(data) { - taskID = data['id']; - trackTask(); - }; - - var trackTask = function() { - kimchi.getTask(taskID, onTaskResponse, err); - }; - - var onTaskResponse = function(result) { - var taskStatus = result['status']; - switch(taskStatus) { - case 'running': - progress && progress(result); - setTimeout(function() { - trackTask(); - }, 200); - break; - case 'finished': - case 'failed': - suc(result); - break; - default: - break; - } - }; - - wok.requestJSON({ - url : 'plugins/kimchi/host/swupdate', - type : "POST", - contentType : "application/json", - dataType : "json", - success : onResponse, - error : err - }); - }, - - createRepository : function(settings, suc, err) { - wok.requestJSON({ - url : "plugins/kimchi/host/repositories", - type : "POST", - contentType : "application/json", - data : JSON.stringify(settings), - dataType : "json", - success: suc, - error: err - }); - }, - - retrieveRepository : function(repository, suc, err) { - var reposID = encodeURIComponent(repository); - wok.requestJSON({ - url : "plugins/kimchi/host/repositories/" + reposID, - type : 'GET', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - - updateRepository : function(name, settings, suc, err) { - var reposID = encodeURIComponent(name); - $.ajax({ - url : "plugins/kimchi/host/repositories/" + reposID, - type : 'PUT', - contentType : 'application/json', - data : JSON.stringify(settings), - dataType : 'json', - success : suc, - error : err - }); - }, - - enableRepository : function(name, enable, suc, err) { - var reposID = encodeURIComponent(name); - $.ajax({ - url : "plugins/kimchi/host/repositories/" + reposID + - '/' + (enable === true ? 'enable' : 'disable'), - type : 'POST', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - - deleteRepository : function(repository, suc, err) { - var reposID = encodeURIComponent(repository); - wok.requestJSON({ - url : 'plugins/kimchi/host/repositories/' + reposID, - type : 'DELETE', - contentType : 'application/json', - dataType : 'json', - success : suc, - error : err - }); - }, - - listRepositories : function(suc, err) { - wok.requestJSON({ - url : 'plugins/kimchi/host/repositories', - type : 'GET', - contentType : 'application/json', - dataType : 'json', - resend: true, - success : suc, - error : err - }); - }, - getHostFCDevices: function(suc, err) { var url = 'plugins/kimchi/host/devices?_cap=fc_host'; wok.requestJSON({ -- 2.1.0